home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-06-17 | 140.7 KB | 5,454 lines |
- head 2.5;
- branch ;
- access ;
- symbols before_fairness_changes:2.0 ckpt1:1.3;
- locks ; strict;
- comment @ * @;
-
-
- 2.5
- date 92.06.16.20.51.54; author jhh; state Exp;
- branches ;
- next 2.4;
-
- 2.4
- date 90.09.24.14.44.39; author douglis; state Exp;
- branches ;
- next 2.3;
-
- 2.3
- date 90.09.14.14.05.45; author douglis; state Exp;
- branches ;
- next 2.2;
-
- 2.2
- date 90.07.05.18.35.27; author douglis; state Exp;
- branches ;
- next 2.1;
-
- 2.1
- date 90.07.05.13.19.25; author douglis; state Exp;
- branches ;
- next 2.0;
-
- 2.0
- date 90.06.30.17.06.57; author douglis; state Stable;
- branches ;
- next 1.14;
-
- 1.14
- date 90.06.30.17.06.07; author douglis; state Exp;
- branches ;
- next 1.13;
-
- 1.13
- date 90.06.26.22.09.03; author douglis; state Exp;
- branches ;
- next 1.12;
-
- 1.12
- date 90.05.28.17.06.38; author douglis; state Exp;
- branches ;
- next 1.11;
-
- 1.11
- date 90.05.14.21.32.59; author douglis; state Exp;
- branches ;
- next 1.10;
-
- 1.10
- date 90.05.03.11.17.32; author douglis; state Exp;
- branches ;
- next 1.9;
-
- 1.9
- date 90.05.02.14.35.35; author douglis; state Exp;
- branches ;
- next 1.8;
-
- 1.8
- date 90.05.02.12.30.46; author douglis; state Exp;
- branches ;
- next 1.7;
-
- 1.7
- date 90.04.27.00.59.05; author douglis; state Exp;
- branches ;
- next 1.6;
-
- 1.6
- date 90.04.24.18.00.32; author douglis; state Exp;
- branches ;
- next 1.5;
-
- 1.5
- date 90.04.03.11.08.25; author douglis; state Exp;
- branches ;
- next 1.4;
-
- 1.4
- date 90.03.14.12.49.38; author douglis; state Exp;
- branches ;
- next 1.3;
-
- 1.3
- date 90.03.12.13.44.57; author douglis; state Exp;
- branches ;
- next 1.2;
-
- 1.2
- date 90.02.28.10.45.36; author douglis; state Exp;
- branches ;
- next 1.1;
-
- 1.1
- date 90.02.15.19.17.39; author douglis; state Exp;
- branches ;
- next ;
-
-
- desc
- @Routines to manage the global loadavg data base.
- @
-
-
- 2.5
- log
- @didn't call Host_End after Host_ByID
- @
- text
- @/*
- * global.c --
- *
- * Routines to manage the global loadavg data base. Only one
- * process is permitted to open the global pdev in master
- * mode and service requests on it. All hosts run a daemon that
- * communicates periodically with the global server. Clients
- * communicate with the global server to obtain load info and request
- * idle hosts. Idle hosts may be released explicitly by ioctls with
- * the server, or implicitly upon closing the pdev connection.
- *
- * The global server maintains an array of structures, one per host,
- * with the load information for each host. The hosts are linked into
- * idle lists, which are distinguished by architecture type and
- * the type of processes running on the hosts. If a host is completely
- * idle, then it is available for any type of process. On the other
- * hand, it might be used by a low priority process, and it could still
- * be used by a higher-priority process but not by another low priority
- * process. In each case, the availability is determined by the
- * number of processors on the host, so a host with 4 processors and
- * three background jobs is presumed to be capable of a fourth background
- * job or up to 4 higher-priority jobs. The queue for completely
- * idle hosts is sorted in order of idle time, but the other queues
- * are just FIFO since if a host already has stuff on it then it
- * is less likely to matter how long it's already been idle. (Maybe
- * this isn't true; in that case, sorting the other queues is
- * always possible.)
- *
- * In addition, the server maintains information about each
- * process that is using idle hosts, and each user. The per-user
- * information is not yet used but may be used to implement a fairness
- * policy at some future date. The per-process information is associated
- * with the pdev handle for the client. If the pdev is closed,
- * all hosts used by that process are marked available.
- *
- * Copyright 1989, 1990 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 2.4 90/09/24 14:44:39 douglis Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
-
- #include <sprite.h>
- #include <string.h>
- #include <list.h>
- #include <errno.h>
- #include <status.h>
- #include "syslog.h"
- #include <bstring.h>
- #include <fs.h>
- #include <kernel/fs.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/dir.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <host.h>
- #include <signal.h>
- #include <pdev.h>
- #include <kernel/net.h>
- #include "mig.h"
- #include "migd.h"
- #include "migPdev.h"
-
- /*
- * Define a structure for keeping track of info we need to send to
- * clients. Each message is a single int.
- */
- typedef struct {
- List_Links links; /* Link to next message. */
- int msg; /* Integer-valued message to tell client. */
- } MessageBlock;
-
- /*
- * A structure is used to keep track of outstanding requests,
- * i.e., idle hosts that have been assigned to a process and not yet
- * returned. It points back to the open stream info and to two linked
- * lists, one that's per stream and one that's per host.
- */
- typedef struct RequestInfo {
- List_Links nextClientRequest; /* Link to next request by same
- client. */
- List_Links nextHostRequest; /* Link to next request for this
- host. */
- List_Links nextInUse; /* Link to next request for this
- machine type and priority. */
- int timestamp; /* Time of request. */
- int priority; /* Priority of processes. */
- int numProcessors; /* Number of processors assigned. */
- int idleTime; /* Idle time of host at time of
- request (in case of eviction,
- for statistics). */
- int flags; /* Flags applied to request. */
- union {
- Migd_OpenStreamInfo *cltPtr; /* Pointer back to open stream info
- for client. */
- int processID; /* ID of process, if agent. */
- } client;
- struct Migd_Info *migdPtr; /* Pointer back to host assigned. */
- } RequestInfo;
-
- #define NEXT_HOST_REQUEST_TO_INFO(listPtr) \
- ( (RequestInfo *)((int)(listPtr) - sizeof(List_Links)) )
-
- #define NEXT_HOST_IN_USE_TO_INFO(listPtr) \
- ( (RequestInfo *)((int)(listPtr) - 2 * sizeof(List_Links)) )
-
- /*
- * Arguments to RevokePermission(). Indicates what to do with client and
- * what to do with statistics gathering.
- */
- typedef enum {
- REVOKE_EVICT, /* Evicting processes. */
- REVOKE_STOLEN, /* Claiming for fairness purposes. */
- REVOKE_IDLE, /* Thought host was unused for a long time. */
- } RevokeAction;
-
- /*
- * Define the number of seconds we'll wait before notifying a process
- * about new hosts being available if we just stole hosts from it.
- */
- #define MIGD_STOLE_WINDOW 30
-
-
- static int maxArchTypes = MIG_MAX_ARCH_TYPES; /* number of elements
- in arrays per-type */
- static char **archTypesArray; /* array of strings mapping types to indexes
- in these arrays */
-
- static int maxHosts = NET_NUM_SPRITE_HOSTS; /* number of hosts in arrays
- per-host */
- static int maxKnownHost = 0; /* Highest known host ID. */
-
- static Migd_Info **migInfoArray; /* array of host info pointers */
- static List_Links *idleHostsArray[MIG_NUM_PRIORITIES];
- /* array of lists of idle hosts,
- indexed by type and priority. */
- static List_Links *inUseArray[MIG_NUM_PRIORITIES];
- /* array of lists of host requests,
- indexed by type and priority. */
- static List_Links *waitingLists[MIG_NUM_PRIORITIES];
- /* array of lists of waiting clients,
- indexed by type. */
-
- static int hostsUp = 0; /* Total number of hosts up, used for
- determining when it's safe to exit after
- termination. */
- static int hostCounts[MIG_MAX_ARCH_TYPES][MIG_NUM_STATES];
- /* Counts per-architecture, per-state. */
-
- static int lastRequestHost = -1; /* ID of last host making a request. */
-
- /*
- * Global variables.
- */
- int global_Debug = 0; /* enable debugging info? */
-
- int global_CheckpointInterval = MIG_TIMEOUT; /* Interval for saving
- checkpoints. */
-
- Mig_Stats global_Stats; /* Statistics, maintained mostly by this
- file. */
-
- #ifndef MIGD_CHECKPOINT_FILE
- #define MIGD_CHECKPOINT_FILE "/sprite/admin/migd/check"
- #endif /* MIGD_CHECKPOINT_FILE */
-
- #ifndef MIGD_LOCK_FILE
- #define MIGD_LOCK_FILE "/sprite/admin/migd/lock"
- #endif /* MIGD_LOCK_FILE */
-
- #ifndef MIGD_LOG_FILE
- #define MIGD_LOG_FILE "/sprite/admin/migd/log"
- #endif /* MIGD_LOG_FILE */
-
- /*
- * Things to keep track of the files used (errors, and lock file).
- */
- char *global_ErrorFile = NULL; /* Place to write host-daemon errors,
- initialized in main. */
- static int lockDesc; /* Descriptor for lock file. */
- static struct stat descAtts; /* Attributes of lock file. */
-
- static void CreateMigdRecord(); /* Allocate a Migd_Info record. */
- static void RestoreCheckPoint(); /* Restore checkpoint from file. */
- static void SaveCheckPoint(); /* Save checkpoint to file. */
- static void CheckHostStatus(); /* Check the status of a host after an
- update. */
- static int RemoveHost(); /* Remove host from list of hosts. */
- static int HostIsIdle(); /* Check for host being idle. */
- static void InsertIdle(); /* Add host to list of idle hosts. */
- static void WakeupWaiters(); /* Wake up processes that want more hosts. */
- static void RecordEvictions(); /* Remove host from idle list and notify
- clients of evictions. */
- static void ForceHostIdle(); /* Make a host seem idle. */
- static void TellClient(); /* Notify a client about a change in
- status. */
- static int CheckFairness(); /* Check on host allocation fairness. */
- static void RevokePermission(); /* Notify a client that its permission to
- use a host has been revoked. */
- static Migd_Info *CltToMigd(); /* Map from client info to migd record. */
-
- static void InitStats(); /* Initialize statistics. */
- static void DumpStats(); /* Dump statistics to file. */
- static int ReadStats(); /* Read statistics from file. */
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_Init --
- *
- * Initialize state of the global server. Called when a process
- * forks and the child tries to become the master for the global
- * pdev.
- *
- * Results:
- * 0 for successful completion, -1 for error, with errno indicating
- * the nature of the error.
- *
- * Side effects:
- * Opens pseudo-device, allocates arrays and assigns architecture strings
- * to indexes.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Global_Init()
- {
- Host_Entry *hostPtr;
- int i, j;
- Time period;
- char pidString[10];
- FILE *logFile;
-
- migd_Pid = getpid();
-
- if (migd_LogToFiles) {
- freopen(migd_GlobalErrorName, "a", stderr);
- #ifdef SEEK_REOPEN
- fseek(stderr, 0L, L_XTND);
- #endif /* SEEK_REOPEN */
- if (fcntl(fileno(stderr), F_SETFL, FAPPEND) < 0) {
- perror("fcntl");
- }
- }
-
- if (global_Debug > 0) {
- int t = time(0);
- fprintf(stderr, "Global_Init - process %x version %u on host %s:\n",
- migd_Pid, migd_Version, migd_HostName);
- fprintf(stderr, "\trun at %s", ctime(&t));
- }
-
- /*
- * We're trying to become the master for the global pdev.
- */
- migd_GlobalMaster = 1;
-
- /*
- * Open pdev. If someone else beats us to it, that's fine, let
- * him handle it.
- */
- if (MigPdev_OpenMaster() < 0){
- return(-1);
- }
-
- /*
- * Create a regular file that we use for detecting changes in master,
- * since unlinking a pdev may cause the file descriptor to be reused
- * prematurely. If we can't create it, there's an error. It may
- * be that right after we unlink it, someone else creates it, in
- * which case that process will become the global master. The pdev
- * is always opened successfully before the lock file is removed
- * and rewritten.
- */
- (void) unlink(MIGD_LOCK_FILE);
- lockDesc = open(MIGD_LOCK_FILE, O_WRONLY|O_CREAT|O_EXCL, 0644);
- if (lockDesc < 0) {
- perror("open (lock file)");
- return(-1);
- }
- sprintf(pidString, "%x\n", migd_Pid);
- if (write(lockDesc, pidString, strlen(pidString) + 1) !=
- strlen(pidString) + 1) {
- perror("write");
- return(-1);
- }
-
- if (fstat(lockDesc, &descAtts) < 0) {
- SYSLOG1(LOG_ERR, "Exiting: unable to stat lock descriptor: %s.\n",
- strerror(errno));
- exit(1);
- }
-
- /*
- * Log a record saying we've started. This is to a separate file from
- * the usual error/debug log.
- */
- logFile = fopen(MIGD_LOG_FILE, "a");
- if (logFile == (FILE *) NULL) {
- fprintf(stderr, "Error opening %s: %s\n", MIGD_LOG_FILE,
- strerror(errno));
- } else {
- int t = time(0);
- fprintf(logFile, "process %x version %u on host %s:\n",
- migd_Pid, migd_Version, migd_HostName);
- fprintf(logFile, "\trun at %s", ctime(&t));
- fclose(logFile);
- }
-
- /*
- * We are the master. Initialize the arrays of hosts and
- * architecture types.
- */
- archTypesArray = (char **) Malloc(sizeof(char *) * maxArchTypes);
- bzero((char *) archTypesArray, sizeof(char *) * maxArchTypes);
-
- migInfoArray = (Migd_Info **) Malloc(sizeof(Migd_Info *) *
- (maxHosts + 1));
- bzero((char *) migInfoArray, sizeof(Migd_Info *) *
- (maxHosts + 1));
-
- /*
- * Go through the host database and set up an empty entry for
- * each host. Also, find all the architecture types to establish
- * a mapping from host to type.
- */
- Host_Start();
- while (1) {
- hostPtr = Host_Next();
- if (hostPtr == (Host_Entry *) NULL) {
- break;
- }
- CreateMigdRecord(hostPtr);
- }
- Host_End();
-
- for (i = 0; i < MIG_NUM_PRIORITIES; i++) {
- idleHostsArray[i] = (List_Links *) Malloc(maxArchTypes *
- sizeof(List_Links));
- inUseArray[i] = (List_Links *) Malloc(maxArchTypes *
- sizeof(List_Links));
- waitingLists[i] = (List_Links *) Malloc(maxArchTypes *
- sizeof(List_Links));
- for (j = 0; j < maxArchTypes; j++) {
- List_Init(&idleHostsArray[i][j]);
- List_Init(&inUseArray[i][j]);
- List_Init(&waitingLists[i][j]);
- }
- }
-
- /*
- * Initialize statistics based on our own idea of the world. This is
- * used to ensure that things haven't changed (for example, the
- * mapping of architecture types to id's).
- */
- InitStats();
-
-
- /*
- * Find out the last time we heard from each host, in order to
- * list downtimes for hosts that aren't currently up. Get the stats
- * saved by the last daemon.
- */
- RestoreCheckPoint();
-
- period.seconds = global_CheckpointInterval;
- period.microseconds = 0;
- Fs_TimeoutHandlerDestroy(migd_TimeoutToken);
- migd_TimeoutToken = Fs_TimeoutHandlerCreate(period, TRUE, SaveCheckPoint,
- (ClientData) NULL);
-
- return (0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * InitStats --
- *
- * Initialize structures relating to statistics. This is called
- * at startup, if an error occurs reading the last checkpoint, or
- * via an ioctl.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The statistics are zeroed, and a few fields are set.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- InitStats()
- {
- int i;
-
- bzero((char *) &global_Stats, sizeof(global_Stats));
- global_Stats.version = migd_Version;
- global_Stats.checkpointInterval = global_CheckpointInterval;
- global_Stats.firstRun = time(0);
- global_Stats.restarts = 1;
- for (i = 0; i < maxArchTypes && i < MIG_MAX_ARCH_TYPES &&
- archTypesArray[i] != (char *) NULL; i++) {
- strncpy(global_Stats.archStats[i].arch, archTypesArray[i],
- MIG_MAX_ARCH_LEN);
- }
- global_Stats.maxArchs = i;
-
- /*
- * All other fields are zero.
- */
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * CreateMigdRecord --
- *
- * Allocate and initialize a Migd_Info record given a Host_Entry
- * record.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Allocates memory. May create a new archType. May increase
- * count of maximum known hostID.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- CreateMigdRecord(hostPtr)
- Host_Entry *hostPtr;
- {
- int archType;
- int host;
- Migd_Info *migdPtr;
- int i;
- char *hp;
- int nameLen;
-
- host = hostPtr->id;
- if (host <= 0) {
- SYSLOG1(LOG_ERR, "invalid host ID from Host_Next: %d.\n",
- host);
- return;
- } else if (host > maxHosts) {
- Migd_Info **newHostArray;
-
- /*
- * Exceeded bounds of array. Make it double the highest
- * host known and continue.
- */
- SYSLOG2(LOG_WARNING,
- "Host identifier (%d) exceeded maximum host ID (%d). Need to recompile program\n.",
- host,
- maxHosts);
- newHostArray = (Migd_Info **) Malloc(sizeof(Migd_Info *) *
- (host * 2 + 1));
- bcopy((char *) migInfoArray, (char *) newHostArray,
- sizeof(Migd_Info *) * (maxHosts + 1));
- bzero((char *) &newHostArray[maxHosts], sizeof(Migd_Info *) *
- (host + 1));
- free((char *) migInfoArray);
- migInfoArray = newHostArray;
- maxHosts = host * 2;
- }
-
- for (i = 0; i < maxArchTypes; i++) {
- if (archTypesArray[i] == (char *) NULL) {
- archTypesArray[i] = Malloc(strlen(hostPtr->machType) + 1);
- strcpy(archTypesArray[i], hostPtr->machType);
- archType = i;
- break;
- }
- if (strcmp(hostPtr->machType, archTypesArray[i]) == 0) {
- archType = i;
- break;
- }
- }
- if (i == maxArchTypes) {
- char **newArray;
- /*
- * Exceeded bounds of array. Double its size and continue.
- */
- SYSLOG0(LOG_WARNING,
- "Too many architecture types -- should recompile program\n.");
- newArray = (char **) Malloc(sizeof(char *) * maxArchTypes * 2);
- bcopy((char *) archTypesArray, (char *) newArray,
- sizeof(char *) * maxArchTypes);
- bzero((char *) &newArray[maxArchTypes], sizeof(char *) *
- maxArchTypes);
- free((char *) archTypesArray);
- archTypesArray = newArray;
- archTypesArray[maxArchTypes] =
- Malloc(strlen(hostPtr->machType) + 1);
- strcpy(archTypesArray[maxArchTypes], hostPtr->machType);
- archType = maxArchTypes;
- maxArchTypes *= 2;
- }
-
- /*
- * Allocate and initialize a record for this host. We assume
- * it is down until we hear from it.
- */
- migdPtr = mnew(Migd_Info);
- bzero((char *) migdPtr, sizeof(Migd_Info));
- migdPtr->archType = archType;
- migdPtr->info.state = MIG_HOST_DOWN;
- hostCounts[archType][MIG_HOST_DOWN]++;
- migdPtr->info.hostID = host;
- if (host > maxKnownHost) {
- maxKnownHost = host;
- }
- migdPtr->lastHostAssigned = -1;
- List_Init(&migdPtr->links);
- List_Init(&migdPtr->clientList);
-
- for (hp = hostPtr->name, nameLen = 0; *hp != '\0' && *hp != '.'; hp++,
- nameLen++) {
- }
- migdPtr->name = Malloc(nameLen + 1);
- bcopy(hostPtr->name, migdPtr->name, nameLen);
- migdPtr->name[nameLen] = '\0';
-
- migInfoArray[host] = migdPtr;
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_End --
- *
- * Terminate service of the master end of the pdev.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The pdev is removed and closed.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Global_End()
- {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "Global_End -\n");
- }
-
-
-
- MigPdev_End();
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "Global_End - exiting.\n");
- }
- (void) unlink(MIGD_LOCK_FILE);
- DATE();
- exit(0);
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_Quit --
- *
- * Called at exit. If any outstanding daemons exist, it tells
- * them to quit as well. This is normally done because of a
- * signal such as SIGINT (i.e., more for debugging than
- * production use). Note, it uses the sprite signal numbering
- * scheme because it bypasses the compatibility library. If
- * there are outstanding clients it doesn't actually exit itself;
- * instead the daemon waits until the last client exits (or
- * another signal occurs).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Clients are signalled and should exit ASAP.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Global_Quit()
- {
- if (hostsUp == 0) {
- Global_End();
- } else {
- MigPdev_SignalClients(SIG_TERM);
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_GetLoadInfo --
- *
- * Get the information for one or more hosts and put it in a buffer.
- * This routine is called via a callback during an ioctl.
- *
- * Results:
- * The size of the output buffer used is returned in *outBufSizePtr.
- * On error, a non-zero error status is returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_GetLoadInfo(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results. */
- int *outBufSizePtr; /* Size of the output buffer, modified with
- amount used. */
- {
- Mig_InfoRequest *infoReqPtr;/* Request from client. */
- int i; /* Counter. */
- int total; /* Number of entries found. */
- int firstHost; /* Sprite ID of first host to return info
- for. */
- int numRecs; /* Maximum number of entries to return. */
- char *bufPtr; /* Pointer into output buffer. */
- Mig_Info *infoPtr; /* Pointer into output buffer. */
- int *totalPtr; /* Pointer into output buffer. */
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetLoadInfo: called from process %x\n",
- cltPtr->processID);
- }
- if (inBufSize != sizeof(Mig_InfoRequest)) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_GetLoadInfo: bad input buffer size (%d) from process %x\n",
- inBufSize, cltPtr->processID);
- }
- return(EINVAL);
- }
- global_Stats.getLoadRequests++;
- infoReqPtr = (Mig_InfoRequest *) inBuffer;
- firstHost = infoReqPtr->firstHost;
- numRecs = infoReqPtr->numRecs;
- if (firstHost <= 0 ||
- *outBufSizePtr < (sizeof(int) + numRecs * sizeof(Mig_Info))) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_GetLoadInfo: bad firstHost argument (%d) or output buffer size (%d)\n",
- firstHost,*outBufSizePtr);
- SYSLOG2(LOG_WARNING,
- "\tfor %d records, from process %x\n", numRecs,
- cltPtr->processID);
- }
- return(EINVAL);
- }
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetLoadInfo: requested %d hosts starting at %d\n",
- numRecs, firstHost);
- }
- bufPtr = outBuffer;
- totalPtr = (int *) bufPtr;
- bufPtr += 2 * sizeof(int);
- infoPtr = (Mig_Info *) bufPtr;
- for (i = firstHost, total = 0; i <= maxKnownHost && total < numRecs;
- i++) {
- if (migInfoArray[i] != (Migd_Info *) NULL &&
- migInfoArray[i]->info.loadVec.timestamp != 0) {
- bcopy((char *) &migInfoArray[i]->info, (char *) infoPtr,
- sizeof(Mig_Info));
- infoPtr++;
- total++;
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetLoadInfo: entry %d is %s\n",
- total, migInfoArray[i]->name);
- }
- }
- }
- *totalPtr = total;
- *outBufSizePtr = 2 * sizeof(int) + total * sizeof(Mig_Info);
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetLoadInfo: returning %d bytes for %d entries.\n",
- *outBufSizePtr, total);
- }
- return(0);
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_GetIdle --
- *
- * Get one or more idle hosts and put their IDs in a buffer.
- * This routine is called via a callback during an ioctl.
- *
- * Results:
- * The size of the output buffer used is returned in *outBufSizePtr.
- * On error, a non-zero error status is returned.
- *
- * Side effects:
- * The hosts obtained may be shuffled to another queue.
- * Allocates various structures.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_GetIdle(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results. */
- int *outBufSizePtr; /* Size of the output buffer, modified with
- amount used. */
- {
- Mig_IdleRequest *idleReqPtr;/* Request from client. */
- int *outPtr; /* Pointer into output buffer. */
- int total; /* Number of entries found. */
- int numHosts; /* Maximum number of host IDs to return. */
- int priority; /* Priority of process. */
- int tryPrio; /* Temporary variable for priority. */
- List_Links *idleList; /* Pointer to header of a list of idle
- hosts. */
- List_Links *listPtr; /* Current element in list. */
- List_Links *nextPtr; /* Next element in list. */
- int archType; /* Numeric identifier for client
- architecture. */
- int migVersion; /* Migration version of requester's host. */
- Migd_Info *migdPtr; /* Pointer to internal form of info for a
- host. */
- Migd_Info *reqMigdPtr; /* Pointer to info for requester's machine. */
- Mig_Info *infoPtr; /* Pointer to external form of info for
- host. */
- RequestInfo *reqPtr; /* Pointer to info for a request. */
- Mig_ArchStats *archPtr; /* For statistics. */
- int retry; /* Used for looping on requests. */
-
- if (inBufSize != sizeof(Mig_IdleRequest)) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_GetIdle: bad input buffer size (%d) from process %x\n",
- inBufSize, cltPtr->processID);
- }
- return(EINVAL);
- }
- idleReqPtr = (Mig_IdleRequest *) inBuffer;
- numHosts = idleReqPtr->numHosts;
-
-
- reqMigdPtr = migInfoArray[cltPtr->host];
- if (reqMigdPtr == (Migd_Info *) NULL ||
- reqMigdPtr->info.state == MIG_HOST_DOWN) {
- if (global_Debug > 0) {
- char buf[10];
- SYSLOG1(LOG_WARNING,
- "Global_GetIdle: no daemon for requester's host (%s).\n",
- reqMigdPtr == (Migd_Info *) NULL ?
- sprintf(buf, "%d", cltPtr->host) : reqMigdPtr->name);
- }
- return(ENOTCONN);
- }
-
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetIdle: request for %d hosts from process %x on %s\n",
- numHosts, cltPtr->processID, reqMigdPtr->name);
- }
-
- priority = idleReqPtr->priority;
- if (numHosts <= 0 ||
- *outBufSizePtr < (1 + numHosts) * sizeof(int) ||
- priority < MIG_LOW_PRIORITY ||
- priority > MIG_HIGH_PRIORITY) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetIdle: bad number of hosts requested (%d), priority (%d), or output buffer size (%d) from process %x\n",
- numHosts, priority, *outBufSizePtr, cltPtr->processID);
- }
- return(EINVAL);
- }
-
- archType = reqMigdPtr->archType;
- migVersion = reqMigdPtr->info.migVersion;
-
- if (migd_DoStats) {
- archPtr = &global_Stats.archStats[archType];
- if (cltPtr->numRequested == 0) {
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetIdle: first request from process %x.\n",
- cltPtr->processID);
- }
- archPtr->numClients++;
- }
- cltPtr->numRequested += numHosts;
- if (cltPtr->numInUse + numHosts > cltPtr->maxRequests) {
- cltPtr->maxRequests = cltPtr->numInUse + numHosts;
- }
- global_Stats.totalRequests += numHosts;
- }
-
- /*
- * Try to assign as many hosts as requested. (At some point we
- * might put in some sort of fairness constraints here.) We
- * look at hosts that are available for the given priority or lower,
- * meaning that a normal priority job can run on a machine that's
- * already being used for a background job but not vice-versa.
- */
-
- outPtr = (int *) (outBuffer + sizeof(int));
-
- total = 0;
- retry = 1;
- while (retry) {
-
- tryPrio = MIG_LOW_PRIORITY;
- while (total < numHosts && tryPrio <= priority) {
- idleList = &idleHostsArray[tryPrio][archType];
- nextPtr = List_First(idleList);
- while (total < numHosts && !List_IsAtEnd(idleList, nextPtr)) {
- listPtr = nextPtr;
- nextPtr = List_Next(nextPtr);
- migdPtr = (Migd_Info *) listPtr;
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Examining %s.\n",
- migdPtr->name);
- }
- if (migdPtr->info.hostID == idleReqPtr->virtHost ||
- migdPtr->info.hostID == cltPtr->host) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Skipping over %s.\n",
- migdPtr->name);
- }
- continue;
- }
- if (migdPtr->info.migVersion != migVersion) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr,
- "Migration version mismatch: %s version %d, %s version %d.\n",
- migdPtr->name, migdPtr->info.migVersion,
- reqMigdPtr->name, migVersion);
- }
- continue;
- }
- infoPtr = (Mig_Info *) &migdPtr->info;
- infoPtr->foreign[priority]++;
- if (infoPtr->foreign[priority] >= infoPtr->maxProcs) {
- /*
- * Used up all the processors on this host for processes
- * of this type, so put the host on the queue for
- * the next higher priority.
- */
- List_Remove(listPtr);
- hostCounts[archType][infoPtr->state]--;
- if (priority < MIG_HIGH_PRIORITY) {
- List_Insert(listPtr,
- LIST_ATREAR(&idleHostsArray
- [priority + 1][archType]));
- infoPtr->state = MIG_HOST_PART_USED;
- } else {
- infoPtr->state = MIG_HOST_FULL;
- }
- hostCounts[archType][infoPtr->state]++;
- }
- /*
- * Allocate a new request info structure and set it up
- * so we can find this request via the host's record or via the
- * client process. Only chain it to the client process if
- * it isn't an "agent" request, since we reclaim hosts on the
- * client's chain of requests when the connection is closed.
- *
- * XXX We'd like to assign multiple processors in a single shot
- * here...
- */
- reqPtr = mnew(RequestInfo);
- reqPtr->priority = priority;
- reqPtr->migdPtr = migdPtr;
- reqPtr->flags = idleReqPtr->flags;
- reqPtr->idleTime = migdPtr->info.loadVec.noInput;
- reqPtr->numProcessors = 1;
- if (! (reqPtr->flags & MIG_PROC_AGENT)) {
- reqPtr->client.cltPtr = cltPtr;
- List_InitElement(&reqPtr->nextClientRequest);
- List_Insert(&reqPtr->nextClientRequest,
- LIST_ATREAR(&cltPtr->currentRequests));
- } else {
- reqPtr->client.processID = cltPtr->processID;
- migdPtr->flags |= MIGD_CHECK_COUNT;
- }
- migdPtr->flags &= ~MIGD_WAS_EMPTY;
- if (migd_DoStats) {
- int noInput;
-
- global_Stats.totalObtained++;
- noInput = (infoPtr->loadVec.noInput + 30) / 60 ;
- reqPtr->timestamp = time(0);
- reqPtr->idleTime = noInput;
- ADD_WITH_OVERFLOW(archPtr->counters.hostIdleObtained, noInput);
- ADD_WITH_OVERFLOW(archPtr->squared.hostIdleObtained,
- noInput * noInput);
- /*
- * Is this host being assigned to the last host that was
- * using it?
- */
- if (migdPtr->lastHostAssigned == cltPtr->host) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "\t** Repeat assignment:\n");
- }
- global_Stats.numRepeatAssignments++;
- } else if (migdPtr->lastHostAssigned == -1) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "\t** First assignment to host:\n");
- }
- global_Stats.numFirstAssignments++;
- }
- migdPtr->lastHostAssigned = cltPtr->host;
-
- if (cltPtr->host == lastRequestHost) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "\t** Repeat requesting host:\n");
- }
- global_Stats.numRepeatRequests++;
- }
- lastRequestHost = cltPtr->host;
- }
-
- List_InitElement(&reqPtr->nextHostRequest);
- List_Insert(&reqPtr->nextHostRequest,
- LIST_ATREAR(&migdPtr->clientList));
-
- List_InitElement(&reqPtr->nextInUse);
- List_Insert(&reqPtr->nextInUse,
- LIST_ATREAR(&inUseArray[priority + 1][archType]));
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "\t** Assigning %s to process %x.\n",
- migdPtr->name, cltPtr->processID);
- }
- total++;
- *outPtr = infoPtr->hostID;
- outPtr++;
- }
- tryPrio++;
- }
- if (total < numHosts) {
- retry = CheckFairness(cltPtr, priority);
- } else {
- retry = 0;
- }
-
- }
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Global_GetIdle: allocated %d hosts to process %x\n",
- total, cltPtr->processID);
- }
-
- outPtr = (int *) outBuffer;
- *outPtr = total;
- *outBufSizePtr = (total + 1) * sizeof(int);
-
- cltPtr->numInUse += total;
- if (migd_DoStats) {
- cltPtr->numObtained += total;
- if (cltPtr->numInUse > cltPtr->maxObtained) {
- cltPtr->maxObtained = cltPtr->numInUse;
- }
- }
-
- if (total < numHosts && cltPtr->waitPtr == (Migd_WaitList *) NULL) {
- List_Links *waitingList = &waitingLists[priority][archType];
- Migd_WaitList *waitPtr = mnew(Migd_WaitList);
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "\t** Process %x put on waiting list.\n",
- cltPtr->processID);
- }
- List_InitElement(&waitPtr->links);
- waitPtr->cltPtr = cltPtr;
- cltPtr->waitPtr = waitPtr;
- List_Insert(&waitPtr->links, LIST_ATREAR(waitingList));
- cltPtr->denied = 1;
- }
-
-
- return(0);
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * CheckFairness --
- *
- * Check on how hosts are allocated to see if hosts should be
- * reclaimed.
- *
- * Results:
- * Returns 1 if more hosts are available, or 0 if not.
- *
- * Side effects:
- * May send message to migration daemons to ask them to evict.
- * Flags the owner of the processes that we kick off so that
- * that process won't be assigned hosts anytime soon if there
- * are other processes that want hosts.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- CheckFairness(cltPtr, priority)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int priority; /* Priority of process allocated. */
- {
- RequestInfo *reqPtr;
- Migd_Info *cltMigdPtr; /* Pointer to info for requesting client's
- machine. */
- Migd_Info *migdPtr; /* Pointer to info for various other
- machines. */
- int migVersion; /* Migration version of requester's host. */
- Migd_OpenStreamInfo *reqCltPtr; /* Client that made request we're looking
- at. */
- RequestInfo *bestReqPtr = NULL; /* Best host we've seen so far. */
- Migd_OpenStreamInfo *bestCltPtr; /* Client using that host with this
- priority. */
- List_Links *listPtr; /* Pointer to chain through list. */
- int okayToUse; /* Flag while stepping through loop. */
- int checkPrio; /* Priority index in loop. */
-
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness called: client %x priority %d.\n",
- cltPtr->processID, priority);
- }
-
-
-
- cltMigdPtr = migInfoArray[cltPtr->host];
- migVersion = cltMigdPtr->info.migVersion;
-
- /*
- * Initialize bestCltPtr to ourselves so we only look at clients
- * with more hosts in use than we have. We also fudge our count
- * to ensure that we don't steal from someone with 2 hosts to give a
- * host to someone with one host.
- */
- bestCltPtr = cltPtr;
- cltPtr->numInUse++;
-
- LIST_FORALL(&inUseArray[priority + 1][cltMigdPtr->archType], listPtr) {
- reqPtr = NEXT_HOST_IN_USE_TO_INFO(listPtr);
- if (reqPtr->flags & (MIG_PROC_AGENT)) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness skipping request on host %d, flags 0x%x.\n",
- reqPtr->migdPtr->info.hostID, reqPtr->flags);
- }
- continue;
- }
- reqCltPtr = reqPtr->client.cltPtr;
- migdPtr = migInfoArray[reqCltPtr->host];
- if (migdPtr->info.migVersion != migVersion) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness skipping request on host %d, migration version %d.\n",
- reqPtr->migdPtr->info.hostID, migdPtr->info.migVersion);
- }
- continue;
- }
- /*
- * We want to see if the host that was already is assigned is the
- * same as the host making the new request, in which case there's
- * no point in reclaiming it since the new requester won't use it.
- */
- if (reqPtr->migdPtr->info.hostID == cltPtr->host) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness skipping request using host %d assigned to process %x: same host as new requester.\n",
- reqPtr->migdPtr->info.hostID, reqCltPtr->processID);
- }
- continue;
- }
- /*
- * Only reclaim a host if it's assigned to only one process, at
- * least for now. Otherwise it will evict a process and we'll
- * never notify the process's agent. We check for a count of 1
- * at the priority we're evicting and 0 elsewhere.
- */
- for (okayToUse = 1, checkPrio = MIG_LOW_PRIORITY;
- okayToUse && checkPrio <= MIG_HIGH_PRIORITY;
- checkPrio++) {
- if (reqPtr->migdPtr->info.foreign[checkPrio] >
- ((priority == checkPrio) ? 1 : 0)) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness skipping request using host %d because more than one client assigned to this host.\n",
- reqPtr->migdPtr->info.hostID);
- }
- okayToUse = 0;
- }
- }
- if (!okayToUse) {
- continue;
- }
- if (global_Debug > 5) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness comparing client %x (%d hosts) to client %x (%d hosts).\n",
- reqCltPtr->processID, reqCltPtr->numInUse,
- bestCltPtr->processID, bestCltPtr->numInUse);
- }
- if (reqCltPtr->numInUse > bestCltPtr->numInUse) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness choosing client %x using %d hosts, this one %d.\n",
- reqCltPtr->processID, reqCltPtr->numInUse,
- bestCltPtr->numInUse);
- }
- bestCltPtr = reqCltPtr;
- bestReqPtr = reqPtr;
- } else if (reqCltPtr == bestCltPtr) {
- bestReqPtr = reqPtr;
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness changing to evict client %x on host %d.\n",
- reqCltPtr->processID, reqPtr->migdPtr->info.hostID);
- }
- }
- }
- /*
- * Undo the fudge factor.
- */
- cltPtr->numInUse--;
- if (bestCltPtr != cltPtr) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "CheckFairness evicting processes on host %s.\n",
- bestReqPtr->migdPtr->name);
- }
- TellClient(bestReqPtr->migdPtr->cltPtr, 0);
- RevokePermission(bestReqPtr, REVOKE_STOLEN);
- List_Remove(&bestReqPtr->nextHostRequest);
- if (HostIsIdle(bestReqPtr->migdPtr)) {
- List_Remove((List_Links *) bestReqPtr->migdPtr);
- }
- InsertIdle(bestReqPtr->migdPtr);
- free(bestReqPtr);
- return(1);
- }
- return(0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_DoneIoctl --
- *
- * Note that a process is through with one or more hosts.
- * This routine is called via a callback during an ioctl.
- * It's really just a stub to call a regular routine without
- * the extra args.
- *
- * Results:
- * On error, a non-zero error status is returned, else 0.
- *
- * Side effects:
- * The hosts are put back on appropriate queues.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_DoneIoctl(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results, not used. */
- int *outBufSizePtr; /* Size of the output buffer, set to 0. */
- {
- int *hostPtr; /* Pointer into input buffer. */
- int i; /* Counter. */
- int numArgs; /* Number of args (host IDs). */
- int status; /* Status from subroutine calls. */
-
- if ((inBufSize % sizeof(int)) != 0 || inBufSize <= 0) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_DoneIoctl: bad input buffer size (%d) from process %x\n",
- inBufSize, cltPtr->processID);
- }
- return(EINVAL);
- }
- numArgs = inBufSize / sizeof(int);
- hostPtr = (int *) inBuffer;
- for (i = 0; i < numArgs; i++, hostPtr++) {
- status = Global_Done(cltPtr, *hostPtr, 0);
- if (status != 0) {
- return(status);
- }
- }
- return(0);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_Done --
- *
- * Note that a process is through with one or more hosts.
- * Takes a single host specification, which may be MIG_ALL_HOSTS
- * to indicate that all hosts are to be returned.
- *
- * Results:
- * Returns 0.
- *
- * Side effects:
- * The hosts may be moved to a different queue. Memory is freed.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Global_Done(cltPtr, host, exiting)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client involved. */
- int host; /* Host specification. */
- int exiting; /* Whether this call is because the process
- is exiting. */
- {
- int priority; /* Priority of process. */
- List_Links *cltList; /* Pointer to header of client's list of
- hosts it's using. */
- List_Links *cltListPtr; /* Pointer into list. */
- List_Links *listPtr; /* Temporary var: pointer to element of list. */
- List_Links *nextPtr; /* For iterations, pointer to next element
- of list. */
- int numReturned = 0; /* Number of hosts returned. */
- Migd_Info *migdPtr; /* Pointer to internal form of info for
- a host. */
- Mig_Info *infoPtr; /* Pointer to external form of info for
- host. */
- RequestInfo *reqPtr; /* Pointer to info for a request. */
- MessageBlock *msgPtr; /* Pointer to message enqueued for client. */
- int returnCode = 0; /* Value to return at end. */
- int requests; /* Number of hosts requested, for statistics. */
- int obtained; /* Number of hosts obtained, for statistics. */
- Mig_ArchStats *archStatsPtr;/* Pointer to per-architecture statistics. */
-
-
- if (global_Debug > 2) {
- if (host) {
- PRINT_PID;
- fprintf(stderr,
- "Global_Done: return %s to free pool for process %x\n",
- migInfoArray[host]->name, cltPtr->processID);
- } else {
- PRINT_PID;
- fprintf(stderr,
- "Global_Done: return all hosts to free pool for process %x\n",
- cltPtr->processID);
- }
- }
-
- /*
- * Check the list of hosts this client is using.
- */
-
-
- cltList = &cltPtr->currentRequests;
- if (List_IsEmpty(cltList)) {
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "Global_Done: process %x has empty client list\n",
- cltPtr->processID);
- }
- goto done;
- }
-
-
-
- cltListPtr = List_First(cltList);
-
- /*
- * Go through list of requests looking for this host, or for each
- * host if so specified.
- */
-
- while (!List_IsAtEnd(cltList, cltListPtr)) {
-
- reqPtr = (RequestInfo *) cltListPtr;
- migdPtr = reqPtr->migdPtr;
- infoPtr = &migdPtr->info;
- priority = reqPtr->priority;
- if (host != MIG_ALL_HOSTS && infoPtr->hostID != host) {
- cltListPtr = List_Next(cltListPtr);
- continue;
- }
- /*
- * Found a record for a host assignment we want to remove.
- * First extract it from the client's list and from the list
- * associated with the host being used.
- */
- listPtr = List_Next(cltListPtr);
- List_Remove(cltListPtr);
- cltListPtr = listPtr;
- listPtr = &reqPtr->nextHostRequest;
- List_Remove(listPtr);
- listPtr = &reqPtr->nextInUse;
- List_Remove(listPtr);
- numReturned++;
-
- infoPtr->foreign[priority] -= reqPtr->numProcessors;
- if (infoPtr->foreign[priority] == infoPtr->maxProcs - 1) {
- /*
- * Now have a free processor on this host for processes
- * of this type, so put the host on the queue for
- * this priority.
- */
- if (HostIsIdle(migdPtr)) {
- List_Remove((List_Links *) migdPtr);
- }
- if (infoPtr->loadVec.allowMigration) {
- InsertIdle(migdPtr);
- } else {
- migdPtr->info.state = MIG_HOST_ACTIVE;
- }
- } else if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Foreign count %d of priority %d on %s not just below maxProcs (%d).\n",
- infoPtr->foreign[priority], priority, migdPtr->name,
- infoPtr->maxProcs);
- }
- if (migd_DoStats) {
- int curTime = time(0);
- int timeUsed = curTime - reqPtr->timestamp;
- global_Stats.archStats[migdPtr->archType].counters.timeUsed +=
- timeUsed;
- global_Stats.archStats[migdPtr->archType].squared.timeUsed +=
- timeUsed * timeUsed;
- }
-
- free ((char *) reqPtr);
- }
-
- done:
- if (exiting) {
- /*
- * Clean up after the process -- get rid of messages, and the message
- * list. Record statistics.
- */
- listPtr = List_First(&cltPtr->messages);
- while (!List_IsAtEnd(&cltPtr->messages, listPtr)) {
- nextPtr = List_Next(listPtr);
- msgPtr = (MessageBlock *) listPtr;
- if (msgPtr->msg == host || host == MIG_ALL_HOSTS) {
- List_Remove(listPtr);
- free((char *) listPtr);
- }
- listPtr = nextPtr;
- }
- if (List_IsEmpty(&cltPtr->messages)) {
- cltPtr->defaultSelBits &= ~FS_READ;
- }
-
- if (cltPtr->waitPtr != (Migd_WaitList *) NULL) {
- List_Remove((List_Links *) cltPtr->waitPtr);
- free((char *) cltPtr->waitPtr);
- cltPtr->waitPtr = (Migd_WaitList *) NULL;
- }
-
- /*
- * Manage statistics. We only count processes that have ever
- * requested hosts, and only when they close their pdev.
- */
- if (migd_DoStats && cltPtr->numRequested > 0) {
- archStatsPtr = &global_Stats.archStats
- [migInfoArray[cltPtr->host]->archType];
- #ifndef min
- #define min(a, b) (((a) < (b)) ? (a) : (b))
- #endif
- requests = min(cltPtr->maxRequests, MIG_MAX_HOSTS_DIST);
- obtained = min(cltPtr->maxObtained, MIG_MAX_HOSTS_DIST);
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr,
- "Global_Done: process %x had a max of %d requests, %d obtained, %d stolen.\n",
- cltPtr->processID, requests, obtained,
- cltPtr->numStolen);
- }
- if (cltPtr->denied == 0) {
- archStatsPtr->gotAll++;
- }
- archStatsPtr->requestDist[requests]++;
- archStatsPtr->obtainedDist[obtained]++;
- archStatsPtr->counters.requested += cltPtr->numRequested;
- archStatsPtr->squared.requested +=
- cltPtr->numRequested * cltPtr->numRequested;
- archStatsPtr->counters.obtained += cltPtr->numObtained;
- archStatsPtr->squared.obtained +=
- cltPtr->numObtained * cltPtr->numObtained;
- archStatsPtr->counters.evicted += cltPtr->numEvicted;
- archStatsPtr->squared.evicted +=
- cltPtr->numEvicted * cltPtr->numEvicted;
- archStatsPtr->counters.reclaimed += cltPtr->numStolen;
- archStatsPtr->squared.reclaimed +=
- cltPtr->numStolen * cltPtr->numStolen;
- }
- }
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "Global_Done: returned %d hosts to pool for process %x\n",
- numReturned, cltPtr->processID);
- }
-
- if (numReturned > 0) {
- cltPtr->stoleTime = 0;
- }
- cltPtr->numInUse -= numReturned;
-
- return(returnCode);
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * InsertIdle --
- *
- * Add a host to the appropriate list of idle hosts, based on
- * the priorities with available capacity. The host must not be
- * on any such list when this procedure is called.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Adds host to list, and sets it state based on whether it has
- * any capacity already used.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- InsertIdle(migdPtr)
- Migd_Info *migdPtr;
- {
- List_Links *listPtr;
- List_Links *hdrPtr;
- int priority;
- int archType = migdPtr->archType;
- Mig_Info *infoPtr;
- Migd_Info *compPtr;
- int noInput;
- int found;
- int origState;
-
-
- WakeupWaiters(archType);
- infoPtr = &migdPtr->info;
- noInput = infoPtr->loadVec.noInput;
- origState = infoPtr->state;
- List_InitElement((List_Links *) migdPtr);
- if (List_IsEmpty(&migdPtr->clientList)) {
- /*
- * Fast path: host is totally idle, so put it in order
- * of idle time on the idle list, and before any
- * hosts with any low priority processes.
- */
- hdrPtr = &idleHostsArray[MIG_LOW_PRIORITY][archType];
- found = 0;
- LIST_FORALL(hdrPtr, listPtr) {
- compPtr = (Migd_Info *) listPtr;
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "InsertIdle: comparing %s (%d secs) to %s (%d secs).\n",
- migdPtr->name, infoPtr->loadVec.noInput,
- compPtr->name, compPtr->info.loadVec.noInput);
- }
- if (compPtr->info.loadVec.noInput < noInput ||
- compPtr->info.foreign[MIG_LOW_PRIORITY] > 0) {
- found = 1;
- break;
- }
- }
- if (found) {
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "Inserting %s before %s\n",
- migdPtr->name, compPtr->name);
- }
- List_Insert((List_Links *) migdPtr, LIST_BEFORE(listPtr));
- } else {
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "Inserting %s at end of list\n",
- migdPtr->name);
- }
- List_Insert((List_Links *) migdPtr, LIST_ATREAR(hdrPtr));
- }
- infoPtr->state = MIG_HOST_IDLE;
- goto done;
- }
-
- /*
- * Look for the first priority that's filled up and put the process
- * on the queue for the next higher priority. If none is filled up,
- * stick it on the end of the low-prio queue, after the hosts with
- * no foreign procs at all.
- */
-
- infoPtr->state = MIG_HOST_PART_USED;
- for (priority = MIG_HIGH_PRIORITY; priority >= MIG_LOW_PRIORITY;
- priority--) {
- if (infoPtr->foreign[priority] == infoPtr->maxProcs) {
- if (priority == MIG_HIGH_PRIORITY) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "%s is actually all taken.\n",
- migdPtr->name);
- }
- infoPtr->state = MIG_HOST_FULL;
- goto done;
- } else {
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "Inserting %s at end of priority %d\n",
- migdPtr->name, priority + 1);
- }
- List_Insert((List_Links *) migdPtr,
- LIST_ATREAR(&idleHostsArray
- [priority + 1][archType]));
- goto done;
- }
- }
- }
- List_Insert((List_Links *) migdPtr,
- LIST_ATREAR(&idleHostsArray[MIG_LOW_PRIORITY][archType]));
-
- done:
- /*
- * If host changed state, modify counters accordingly.
- */
- if (origState != infoPtr->state) {
- hostCounts[archType][origState]--;
- hostCounts[archType][infoPtr->state]++;
- }
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * WakeupWaiters --
- *
- * Check to see if anyone is waiting for an idle host. Wake up all
- * processes waiting for available hosts of this type, if a host is
- * available at the appropriate priority. Then let them ask again for
- * an idle host using normal ioctls.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Makes pdevs for clients readable so they know to contact us.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- WakeupWaiters(archType)
- int archType;
- {
- List_Links *waitingList;
- List_Links *listPtr;
- Migd_WaitList *waitPtr;
- Migd_OpenStreamInfo *cltPtr;
- MessageBlock *msgPtr;
- int curTime;
- int priority;
- int i;
-
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr,
- "WakeupWaiters(%s) called.\n", archTypesArray[archType]);
- }
- curTime = time(0);
- for (priority = MIG_HIGH_PRIORITY; priority >= MIG_LOW_PRIORITY;
- priority--) {
- if (!List_IsEmpty(&idleHostsArray[priority][archType])) {
- for (i = priority; i <= MIG_HIGH_PRIORITY; i++) {
- waitingList = &waitingLists[priority][archType];
- while (!List_IsEmpty(waitingList)) {
- /*
- * For each process waiting, get rid of the info saying it's
- * waiting and instead add a message to the process.
- */
- listPtr = List_First(waitingList);
- waitPtr = (Migd_WaitList *) listPtr;
- List_Remove(listPtr);
- cltPtr = waitPtr->cltPtr;
- cltPtr->waitPtr = (Migd_WaitList *) NULL;
- if (cltPtr->stoleTime > curTime - MIGD_STOLE_WINDOW) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "\t** not telling process %x about host available, since we stole from it recently.\n",
- cltPtr->processID);
- }
- } else {
- TellClient(cltPtr, 0);
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "\t** telling process %x about host available.\n",
- cltPtr->processID);
- }
- }
- free((char *) waitPtr);
- }
- }
- }
- }
- }
-
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RecordEvictions --
- *
- * A host is evicting foreign processes. Make sure it's marked
- * appropriately, and clean up any state from foreign processes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Notifies clients of eviction [eventually]. Frees memory associated
- * with outstanding requests for host.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- RecordEvictions(migdPtr)
- Migd_Info *migdPtr;
- {
- int down;
- List_Links *listPtr;
- RequestInfo *reqPtr;
- Migd_OpenStreamInfo *cltPtr;
- int priority;
- Mig_ArchStats *archPtr; /* For statistics. */
-
-
- down = migdPtr->info.state == MIG_HOST_DOWN;
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "RecordEvictions: %s %s.\n",
- migdPtr->name, down ? "down" : "evicting foreigners");
- }
-
- if (migd_DoStats) {
- archPtr = &global_Stats.archStats[migdPtr->archType];
- if (!down) {
- int noInput = (migdPtr->info.loadVec.noInput + 30) / 60 ;
- archPtr->nonIdleTransitions++;
- ADD_WITH_OVERFLOW(archPtr->counters.idleTimeWhenActive,
- noInput);
- ADD_WITH_OVERFLOW(archPtr->squared.idleTimeWhenActive,
- noInput * noInput);
- }
- }
-
-
- while (!List_IsEmpty(&migdPtr->clientList)) {
- listPtr = List_First(&migdPtr->clientList);
- List_Remove(listPtr);
- reqPtr = NEXT_HOST_REQUEST_TO_INFO(listPtr);
- if (global_Debug > 1 && !down) {
- PRINT_PID;
- fprintf(stderr, "RecordEvictions: %s evicting client %x.\n",
- migdPtr->name,
- (reqPtr->flags & MIG_PROC_AGENT) ?
- reqPtr->client.processID :
- reqPtr->client.cltPtr->processID);
- }
- RevokePermission(reqPtr, REVOKE_EVICT);
-
- if (migd_DoStats) {
- int curTime = time(0);
- int timeToEviction = curTime - reqPtr->timestamp;
- archPtr->counters.timeToEviction += timeToEviction;
- archPtr->squared.timeToEviction += timeToEviction * timeToEviction;
- ADD_WITH_OVERFLOW(archPtr->counters.hostIdleEvicted,
- reqPtr->idleTime);
- ADD_WITH_OVERFLOW(archPtr->squared.hostIdleEvicted,
- reqPtr->idleTime * reqPtr->idleTime);
-
- }
- free((char *) reqPtr);
- }
- migdPtr->flags &= ~(MIGD_CHECK_COUNT | MIGD_WAS_EMPTY);
- for (priority = MIG_LOW_PRIORITY; priority <= MIG_HIGH_PRIORITY;
- priority++) {
- migdPtr->info.foreign[priority] = 0;
- }
- /*
- * Clear out the last host assignment, since after a machine evicts or
- * crashes we don't care who last used it.
- */
- migdPtr->lastHostAssigned = -1;
-
- if (HostIsIdle(migdPtr)) {
- List_Remove((List_Links *) migdPtr);
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * TellClient --
- *
- * Pass a number to a client. It's either the ID of a host that
- * it no longer has permission to use, or 0 to indicate a new host
- * may be available.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Allocates a message buffer and adds it to the clients list. Makes
- * the client pdev readable.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- TellClient(cltPtr, msg)
- Migd_OpenStreamInfo *cltPtr; /* Info about client. */
- int msg; /* ID of host, or 0. */
- {
- MessageBlock *msgPtr;
-
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "TellClient: telling client %x value %d.\n",
- cltPtr->processID, msg);
- }
-
- msgPtr = mnew(MessageBlock);
- List_InitElement(&msgPtr->links);
- msgPtr->msg = msg;
- if (List_IsEmpty(&cltPtr->messages)) {
- MigPdev_MakeReady(cltPtr->streamPtr, (ClientData) NULL);
- }
- List_Insert((List_Links *) msgPtr, LIST_ATREAR(&cltPtr->messages));
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RevokePermission --
- *
- * Notify a client that it has lost its permission to use a host.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sends a message. Removes request from per-client list and per-machine
- * list.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- RevokePermission(reqPtr, action)
- RequestInfo *reqPtr;
- RevokeAction action;
- {
- Migd_Info *migdPtr;
- Migd_OpenStreamInfo *cltPtr;
-
- migdPtr = reqPtr->migdPtr;
- migdPtr->info.foreign[reqPtr->priority] -= reqPtr->numProcessors;
-
- List_Remove(&reqPtr->nextInUse);
- #ifdef DEBUG_LIST_REMOVE
- /*
- * Zap the element just to be sure.
- */
- List_InitElement(&reqPtr->nextInUse);
- #endif /* DEBUG_LIST_REMOVE */
-
- if (!(reqPtr->flags & MIG_PROC_AGENT)) {
- List_Remove((List_Links *) reqPtr);
- cltPtr = reqPtr->client.cltPtr;
- TellClient(cltPtr, migdPtr->info.hostID);
- cltPtr->numInUse--;
- if (cltPtr->numInUse == 0) {
- cltPtr->stoleTime = 0;
- }
- if (action == REVOKE_EVICT) {
- cltPtr->numEvicted++;
- } else if (action == REVOKE_STOLEN) {
- cltPtr->numStolen++;
- cltPtr->stoleTime = time(0);
- }
- } else if (action == REVOKE_STOLEN) {
- /*
- * Request was on behalf of another process, so we don't
- * increment the client numStolen field and instead add it
- * in to the totals independently. (For regular clients we
- * accumulate multiple reclaims/client and then the "squared"
- * statistic weights clustered reclaimed hosts.)
- */
- if (migd_DoStats) {
- global_Stats.archStats[migdPtr->archType].counters.reclaimed++;
- global_Stats.archStats[migdPtr->archType].squared.reclaimed++;
- }
- } else if (action == REVOKE_EVICT) {
- /*
- * Request was on behalf of another process, so we don't
- * increment the client numEvicted field and instead add it
- * in to the totals independently. (For regular clients we
- * accumulate multiple evictions/client and then the "squared"
- * statistic weights clustered evictions.)
- */
- if (migd_DoStats) {
- global_Stats.archStats[migdPtr->archType].counters.evicted++;
- global_Stats.archStats[migdPtr->archType].squared.evicted++;
- }
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_GetUpdate --
- *
- * Return an update message to a client. This is an ioctl
- * invoked by the client when the client's stream becomes
- * readable.
- *
- * Results:
- * On error, a non-zero error status is returned, else 0.
- *
- * Side effects:
- * The message is freed up. If it's the last message in the
- * client's queue, the client is changed to no longer be selectable.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_GetUpdate(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from, not used. */
- int inBufSize; /* Size of the input buffer, not used. */
- char *outBuffer; /* Buffer to place results. */
- int *outBufSizePtr; /* Size of the output buffer. */
- {
- int *intPtr;
- List_Links *listPtr;
- MessageBlock *msgPtr;
-
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Global_GetUpdate called by process %x\n",
- cltPtr->processID);
- }
- if (*outBufSizePtr < sizeof(int)) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_GetUpdate: bad output buffer size (%d) from process %x\n",
- *outBufSizePtr, cltPtr->processID);
- }
- return(EINVAL);
- }
- if (List_IsEmpty(&cltPtr->messages)) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetUpdate: no message for process %x\n",
- cltPtr->processID);
- }
- return(EAGAIN);
- }
- listPtr = List_First(&cltPtr->messages);
- List_Remove(listPtr);
- if (List_IsEmpty(&cltPtr->messages)) {
- cltPtr->defaultSelBits &= ~FS_READ;
- }
- msgPtr = (MessageBlock *) listPtr;
- intPtr = (int *) outBuffer;
- *intPtr = msgPtr->msg;
- *outBufSizePtr = sizeof(int);
- free((char *) listPtr);
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Global_GetUpdate: message for process %x is %d\n",
- cltPtr->processID, msgPtr->msg);
- }
- return(0);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_RemoveHost --
- *
- * Remove a host completely from the database. This may be done
- * when a host is removed from the system, for example.
- *
- * Results:
- * On error, a non-zero error status is returned, else 0.
- *
- * Side effects:
- * The host(s) are removed from our lists and a new checkpoint is
- * written.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_RemoveHost(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results, not used. */
- int *outBufSizePtr; /* Size of the output buffer, set to 0. */
- {
- int *hostPtr; /* Pointer into input buffer. */
- int i; /* Counter. */
- int numArgs; /* Number of args (host IDs). */
- int status; /* Status from subroutine calls. */
-
- if ((inBufSize % sizeof(int)) != 0 || inBufSize <= 0) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_RemoveHost: bad input buffer size (%d) from process %x\n",
- inBufSize, cltPtr->processID);
- }
- return(EINVAL);
- }
- numArgs = inBufSize / sizeof(int);
- hostPtr = (int *) inBuffer;
- for (i = 0; i < numArgs; i++) {
- status = RemoveHost(*hostPtr);
- if (status != 0) {
- return(status);
- }
- }
- SaveCheckPoint((ClientData) NULL, time_ZeroSeconds);
- return(0);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RemoveHost --
- *
- * Remove a single host from our knowledge.
- *
- * Results:
- * On error, a non-zero error status is returned, else 0.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- RemoveHost(hostID)
- int hostID; /* Host to remove. */
- {
- Migd_Info *migdPtr;
-
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "RemoveHost(%d) -\n", hostID);
- }
-
- if (hostID > maxHosts || hostID <= 0) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "RemoveHost: bad value of hostID: %d\n", hostID);
- }
- return(EINVAL);
- }
- migdPtr = migInfoArray[hostID];
- if (migdPtr != (Migd_Info *) NULL) {
- if (migdPtr->info.state != MIG_HOST_DOWN) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "RemoveHost: %s is up; not removing.\n",
- migdPtr->name);
- }
- return(EINVAL);
- }
- if (migdPtr->name != (char *) NULL) {
- free(migdPtr->name);
- }
- free((char *) migdPtr);
- migInfoArray[hostID] = (Migd_Info *) NULL;
- } else if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "RemoveHost(%d) - didn't know about host.\n", hostID);
- }
- return(0);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_IsHostUp --
- *
- * Return whether the specified host is up.
- *
- * Results:
- * TRUE if the host exists and is up, FALSE otherwise.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Global_IsHostUp(hostID)
- int hostID; /* Host to check on. */
- {
- Migd_Info *migdPtr;
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "Global_IsHostUp(%d) -\n", hostID);
- }
-
- if (hostID > maxHosts || hostID <= 0) {
- SYSLOG1(LOG_ERR, "Global_IsHostUp: bad value of hostID: %d\n", hostID);
- return(0);
- }
- migdPtr = migInfoArray[hostID];
- if ((migdPtr != (Migd_Info *) NULL) &&
- (migdPtr->info.state != MIG_HOST_DOWN)) {
- return(1);
- }
- return(0);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_ChangeState --
- *
- * A host has changed from accepting processes to not accepting them,
- * or vice-versa. If not accepting, then notify processes about
- * any evictions that might have occurred.
- *
- * Results:
- * On error, a non-zero error status is returned, else 0.
- *
- * Side effects:
- * Message(s) sent to clients. Host may be added to or removed from
- * list of idle hosts.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_ChangeState(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results, not used. */
- int *outBufSizePtr; /* Size of the output buffer, set to 0. */
- {
- int *statePtr;
- int host;
- Migd_Info *migdPtr;
-
- if (cltPtr->type != MIGD_DAEMON) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "Global_ChangeState: non-daemon trying to invoke CHANGE ioctl; pid %x state %x\n",
- cltPtr->processID, (int) cltPtr->type);
- }
- return(EPERM);
- }
-
- if (inBufSize != sizeof(int)) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_ChangeState: wrong size input (%d bytes) from process %x\n",
- inBufSize, cltPtr->processID);
- }
- return(EINVAL);
- }
-
- host = cltPtr->host;
- statePtr = (int *) inBuffer;
-
- migdPtr = CltToMigd(cltPtr);
- if (migdPtr == (Migd_Info *) NULL) {
- SYSLOG0(LOG_ERR, "Global_ChangeState: never heard from this host? Exiting.\n");
- exit(1);
- }
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "Global_ChangeState called for %s => state %d.\n",
- migdPtr->name,
- *statePtr);
- }
-
- switch (*statePtr) {
- case MIG_HOST_ACTIVE:
- case MIG_HOST_REFUSES: {
- /*
- * Host is evicting any foreign processes.
- */
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Host is active or is refusing migration.\n");
- }
- RecordEvictions(migdPtr);
- break;
- }
- case MIG_HOST_IDLE: {
- /*
- * Actually, this case should never be reached.
- */
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "Changed state to idle??\n");
- }
- InsertIdle(migdPtr);
- break;
- }
- default: {
- PRINT_PID;
- fprintf(stderr, "Invalid state!\n");
- return(EINVAL);
- }
- }
- hostCounts[migdPtr->archType][migdPtr->info.state]--;
- migdPtr->info.state = *statePtr;
- hostCounts[migdPtr->archType][migdPtr->info.state]++;
-
- return(0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_HostUp --
- *
- * Mark a host as being up, the first time its daemon talks to us.
- *
- * Results:
- * 0 for success, or an errno indicating the error.
- * EPERM indicates that a non-root process tried to tell us it
- * was the daemon.
- *
- * Side effects:
- * The host is added to the list of active hosts.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_HostUp(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results, not used. */
- int *outBufSizePtr; /* Size of the output buffer, set to 0. */
- {
- Mig_Info *infoPtr;
- Migd_Info *migdPtr;
- Host_Entry *hostPtr;
- Migd_OpenStreamInfo *oldCltPtr; /* Information about any previous client
- from this host. */
- int status;
- struct timeval time;
-
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Global_HostUp called.\n");
- }
-
- status = gettimeofday(&time, (struct timezone *) NULL);
- if (status == -1) {
- SYSLOG1(LOG_ERR, "Error in gettimeofday: %s", strerror(errno));
- exit(1);
- }
-
- if (inBufSize != sizeof(Mig_Info)) {
- if (global_Debug > 0) {
- SYSLOG2(LOG_WARNING,
- "Global_HostUp: bad input buffer size (%d) from process %x\n",
- inBufSize, cltPtr->processID);
- }
- return(EINVAL);
- }
-
- /*
- * Flag a connection as belonging to a daemon, permitting
- * it to perform privileged operations. Set the format
- * value in the info struct, so that writes can be swapped if
- * needed.
- */
- #ifndef DEBUG
- if (global_Debug == 0 && cltPtr->user != PROC_SUPER_USER_ID) {
- return(EPERM);
- }
- #endif /* DEBUG */
-
-
- infoPtr = (Mig_Info *) inBuffer;
-
- if (cltPtr->host > maxHosts) {
- /*
- * XXX We should handle this obscure case by growing the array of
- * hosts, but skip it for the time being.
- */
- SYSLOG1(LOG_ERR,
- "Never heard of host %d, and ID is too big.\n", cltPtr->host);
- return(EINVAL);
- }
- if (migInfoArray[cltPtr->host] == (Migd_Info *) NULL) {
- /*
- * This can happen if a new host is added to the system
- * after the global daemon starts up, or a host record has been
- * removed.
- */
- hostPtr = Host_ByID(cltPtr->host);
- if (hostPtr == (Host_Entry *) NULL) {
- SYSLOG1(LOG_ERR, "No entry in host database for host %d.\n",
- cltPtr->host);
- return(EINVAL);
- }
- CreateMigdRecord(hostPtr);
- Host_End();
- }
- migdPtr = migInfoArray[cltPtr->host];
-
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Global_HostUp - %s pid %x boot %d version %d maxProcs %d\n",
- migdPtr->name, cltPtr->processID,
- infoPtr->bootTime, infoPtr->migVersion,
- infoPtr->maxProcs);
- }
-
- if (migdPtr->cltPtr != (Migd_OpenStreamInfo *) NULL) {
- oldCltPtr = migdPtr->cltPtr;
- /*
- * Check once again whether the host is really down. If a host reboots
- * quickly, we might otherwise think it's still up and try to signal
- * a process. If we're really unlikely, the host rebooted and the
- * process of the new daemon is the same as the daemon the last time
- * the host was up, and we'll kill the new daemon (or some other
- * random process). We could solve this problem if each boot
- * incremented some version number that got passed to the global
- * daemon, but we don't have such a capability (yet).
- *
- * Another potential problem: the host migd gets a stale handle
- * and closes and reopens the global pdev, and we have to recognize
- * that and refrain from terminating it as if it were a leftover
- * migd process.
- */
- if (oldCltPtr->processID == cltPtr->processID) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Global_HostUp - %s reopening unclosed connection.\n",
- migdPtr->name);
- }
- (void) Global_HostDown(cltPtr->host, 0);
- } else if (migdPtr->info.loadVec.timestamp <
- time.tv_sec - MIG_TIMEOUT) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Global_HostUp - marking %s down (curTime %d, updated %d).\n",
- migdPtr->name, time.tv_sec,
- migdPtr->info.loadVec.timestamp);
- }
- (void) Global_HostDown(cltPtr->host, 0);
- }
- if (migdPtr->info.state != MIG_HOST_DOWN) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Already talking to a daemon on %s. Signalling pid %x.\n",
- migdPtr->name, oldCltPtr->processID);
- }
- status = Sig_Send(SIG_TERM, oldCltPtr->processID, 0);
- if (status != SUCCESS) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr, "SendSignal: error sending signal to process %x: %s\n",
- oldCltPtr->processID, Stat_GetMsg(status));
- }
- Global_HostDown(cltPtr->host, 0);
- } else {
- return(EBUSY);
- }
- } else {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "Received new open from host %s; closing prior stream.\n",
- migdPtr->name);
- }
- }
- }
-
- /*
- * Check for migds that are a bit confused about their state.
- */
- if (infoPtr->state == MIG_HOST_IDLE && !infoPtr->loadVec.allowMigration) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "Host %s marked as idle but not allowing migration.\n",
- migdPtr->name);
- }
- infoPtr->state = MIG_HOST_REFUSES;
- }
- #ifdef USE_GLOBAL_CLOCK
- /*
- * Update the time of day to use the global daemon's idea of the time,
- * to keep things in sync and avoid calling a client down just because
- * of clock skew. Check the bootstamp for clock skew too.
- */
- infoPtr->loadVec.timestamp = time.tv_sec;
- if (infoPtr->bootTime > time.tv_sec) {
- infoPtr->bootTime = time.tv_sec;
- }
- #endif /* USE_GLOBAL_CLOCK */
- migdPtr->info = *infoPtr;
- migdPtr->cltPtr = cltPtr;
- cltPtr->type = MIGD_DAEMON;
- cltPtr->defaultSelBits = FS_WRITE;
-
- /*
- * Add the host to appropriate queue, and modify our counters.
- */
- hostCounts[migdPtr->archType][MIG_HOST_DOWN]--;
- hostCounts[migdPtr->archType][infoPtr->state]++;
- if (infoPtr->state == MIG_HOST_IDLE) {
- InsertIdle(migdPtr);
- }
-
- hostsUp++;
-
- return(0);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * EndCallBack --
- *
- * Just a callback used by Fs_Dispatch when we want to quit
- * but can't at the moment. It takes (and ignores) the
- * Fs_Dispatch callback arguments.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Global_End is called, and the process exits.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static void
- EndCallBack(clientData, time)
- ClientData clientData; /* Generic callback arg, not used. */
- Time time; /* Generic callback arg, not used. */
- {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "EndCallBack -\n");
- }
-
- Global_End();
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_HostDown --
- *
- * Mark a host as being down. This may happen when a pdev for the
- * daemon on that host is closed, or if it doesn't update its information
- * in a timely fashion. If it's really closed, we clean up state
- * associated with it.
- *
- * Results:
- * 0 for success, or -1 and an errno for failure.
- *
- * Side effects:
- * The host is removed from any lists of active hosts. Any clients
- * accessing the host are notified that it is down.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Global_HostDown(hostID, closed)
- int hostID;
- int closed; /* whether its stream was closed */
- {
- Migd_Info *migdPtr;
-
- if (hostID > maxHosts || migInfoArray[hostID] == (Migd_Info *) NULL) {
- PRINT_PID;
- fprintf(stderr, "Global_HostDown: bad value of hostID: %d\n",
- hostID);
- errno = EINVAL;
- return(-1);
- }
- migdPtr = migInfoArray[hostID];
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Global_HostDown(host=%s(%d), closed=%d) called.\n",
- migdPtr->name, hostID, closed);
- }
-
- if (closed) {
- /*
- * We're no longer talking to the daemon with a pdev connection.
- */
- migdPtr->cltPtr = (Migd_OpenStreamInfo *) NULL;
- } else {
- /*
- * This connection is unusable... later closes should be ignored.
- */
- migdPtr->cltPtr->type = MIGD_CLOSED;
- }
- if (HostIsIdle(migdPtr)) {
- List_Remove((List_Links *) migdPtr);
- }
- hostCounts[migdPtr->archType][migdPtr->info.state]--;
- migdPtr->info.state = MIG_HOST_DOWN;
- hostCounts[migdPtr->archType][MIG_HOST_DOWN]++;
- RecordEvictions(migdPtr);
-
- hostsUp--;
- if (hostsUp <= 0 && migd_Quit) {
- if (closed) {
- /*
- * Set up a callback to exit, rather than doing it right now,
- * since we want to return from any Pdev_Close callback before
- * trying to close the master.
- */
- Fs_TimeoutHandlerDestroy(migd_TimeoutToken);
- (void) Fs_TimeoutHandlerCreate(time_ZeroSeconds, TRUE,
- EndCallBack, (ClientData) NULL);
- } else {
- Global_End();
- }
- }
- return(0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_UpdateLoad --
- *
- * Update the load vector corresponding to a host.
- *
- * Results:
- * 0 for success, or -1 for failure, with errno indicating the error.
- *
- * Side effects:
- * The host may be moved from one queue to another if its status
- * changes.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Global_UpdateLoad(cltPtr, vecPtr)
- Migd_OpenStreamInfo *cltPtr;
- Mig_LoadVector *vecPtr;
- {
- int host;
- Migd_Info *migdPtr;
- Mig_LoadVector *oldVecPtr;
- int oldAllow;
- int oldForeign;
- int status;
- struct timeval time;
-
- host = cltPtr->host;
-
- migdPtr = CltToMigd(cltPtr);
- if (migdPtr == (Migd_Info *) NULL) {
- SYSLOG0(LOG_ERR, "Global_UpdateLoad: never heard from this host? Exiting.\n");
- exit(1);
- }
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Global_UpdateLoad called for %s. time %d noInput %d foreign %d allowMigration %d utils %d %d %d lengths %.2f %.2f %.2f\n",
- migdPtr->name,
- vecPtr->timestamp,
- vecPtr->noInput,
- vecPtr->foreignProcs,
- vecPtr->allowMigration,
- vecPtr->utils[0], vecPtr->utils[1], vecPtr->utils[2],
- vecPtr->lengths[0], vecPtr->lengths[1], vecPtr->lengths[2]);
- }
- if (migdPtr->info.state == MIG_HOST_DOWN) {
- if (global_Debug) {
- PRINT_PID;
- fprintf(stderr, "Global_UpdateLoad: Thought %s was down.\n",
- migdPtr->name);
- }
- hostCounts[migdPtr->archType][MIG_HOST_DOWN]--;
- migdPtr->info.state = vecPtr->allowMigration ? MIG_HOST_ACTIVE :
- MIG_HOST_REFUSES;
- hostCounts[migdPtr->archType][migdPtr->info.state]++;
- hostsUp++;
- }
- oldVecPtr = &migdPtr->info.loadVec;
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Global_UpdateLoad: Old values: time %d noInput %d foreign %d allowMigration %d utils %d %d %d lengths %.2f %.2f %.2f\n",
- oldVecPtr->timestamp,
- oldVecPtr->noInput,
- oldVecPtr->foreignProcs,
- oldVecPtr->allowMigration,
- oldVecPtr->utils[0],
- oldVecPtr->utils[1],
- oldVecPtr->utils[2],
- oldVecPtr->lengths[0],
- oldVecPtr->lengths[1],
- oldVecPtr->lengths[2]);
- }
- oldAllow = oldVecPtr->allowMigration;
- oldForeign = oldVecPtr->foreignProcs;
- *oldVecPtr = *vecPtr;
-
- #ifdef USE_GLOBAL_CLOCK
- /*
- * Update the time of day to use the global daemon's idea of the time,
- * to keep things in sync and avoid calling a client down just because
- * of clock skew.
- */
- status = gettimeofday(&time, (struct timezone *) NULL);
- if (status == -1) {
- SYSLOG1(LOG_ERR, "Error in gettimeofday: %s", strerror(errno));
- exit(1);
- }
- oldVecPtr->timestamp = time.tv_sec;
- #endif /* USE_GLOBAL_CLOCK */
- if (oldAllow && !vecPtr->allowMigration) {
- /*
- * Host is evicting any foreign processes.
- */
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "\t>>%s is no longer available<<\n", migdPtr->name);
- }
- if (HostIsIdle(migdPtr)) {
- List_Remove((List_Links *) migdPtr);
- }
- hostCounts[migdPtr->archType][migdPtr->info.state]--;
- migdPtr->info.state = MIG_HOST_ACTIVE;
- hostCounts[migdPtr->archType][MIG_HOST_ACTIVE]++;
- } else if (!oldAllow && vecPtr->allowMigration) {
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "\t<<%s is now idle>>\n", migdPtr->name);
- }
- if (HostIsIdle(migdPtr)) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "\t ** %s wasn't allowing migration but was idle\n",
- migdPtr->name);
- }
- } else {
- InsertIdle(migdPtr);
- }
- } else if (vecPtr->allowMigration && (migdPtr->flags & MIGD_CHECK_COUNT) &&
- (migdPtr->info.state == MIG_HOST_FULL ||
- migdPtr->info.state == MIG_HOST_PART_USED)) {
- if (oldForeign > 0 && vecPtr->foreignProcs == 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "\t--%s now has no foreigners--\n",
- migdPtr->name);
- }
- ForceHostIdle(migdPtr);
- } else if (vecPtr->foreignProcs > 0) {
- /*
- * If during a checkpoint we noticed that the host was empty, and
- * now it isn't, we disable the MIGD_WAS_EMPTY flag. This
- * way a host will be marked as having no foreign processes
- * and put back in the pool only if two checkpoints go by without
- * the host ever having foreign processes at the points when the
- * per-host migd sends us its data.
- */
- migdPtr->flags &= ~MIGD_WAS_EMPTY;
- }
- } else if (vecPtr->allowMigration &&
- (migdPtr->info.state == MIG_HOST_ACTIVE) &&
- vecPtr->foreignProcs == 0) {
- /*
- * Host must have evicted without later making the transition
- * from not allowing to allowing. This can happen if eviction
- * takes a long time or if eviction is done via an ioctl from
- * a user rather than by detecting input.
- */
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "\t--%s available again--\n",
- migdPtr->name);
- }
- ForceHostIdle(migdPtr);
- }
- return(0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * RestoreCheckPoint --
- *
- * Restore the last known state of the world from a checkpoint
- * file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The state of each host in the checkpoint, and the statistics structure,
- * are initialized.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- RestoreCheckPoint()
- {
-
- FILE *checkPoint;
- int hostID;
- int timestamp;
- Migd_Info *migdPtr;
- int numScanned;
- int hostsRead = 0;
- char buffer[BUFSIZ];
-
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "RestoreCheckPoint -\n");
- }
- checkPoint = fopen(MIGD_CHECKPOINT_FILE, "r");
- if (checkPoint == (FILE *) NULL) {
- PRINT_PID;
- fprintf(stderr, "RestoreCheckPoint - error reading checkpoint: %s.\n",
- strerror(errno));
- return;
- }
- if (ReadStats(checkPoint) < 0) {
- PRINT_PID;
- SYSLOG1(stderr,
- "warning: RestoreCheckPoint - error reading statistics from checkpoint: %s.\n",
- strerror(errno));
- /*
- * Reinitialize statistics buffer.
- */
- InitStats();
- }
- while (1) {
- if (fgets(buffer, sizeof(buffer), checkPoint) == (char *) NULL) {
- break;
- }
- if (buffer[0] == '%') {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "RestoreCheckPoint: %s",
- buffer);
- }
- continue;
- }
- numScanned = sscanf(buffer, "%d %d", &hostID, ×tamp);
- if (numScanned < 0) {
- break;
- }
- if (numScanned != 2) {
- PRINT_PID;
- fprintf(stderr,
- "RestoreCheckPoint - scanned %d items from checkpoint file.\n",
- numScanned);
- break;
- }
- if (hostID <= 0 || hostID > maxKnownHost) {
- PRINT_PID;
- fprintf(stderr,
- "RestoreCheckPoint - invalid hostID %d.\n", hostID);
- break;
- }
- migdPtr = migInfoArray[hostID];
- if (migdPtr == (Migd_Info *) NULL ||
- migdPtr->info.loadVec.timestamp != 0) {
- PRINT_PID;
- fprintf(stderr,
- "RestoreCheckPoint - host %d NULL or non-zero.\n", hostID);
- break;
- }
- if (global_Debug > 2) {
- fprintf(stderr,
- "<%d,%d> ",
- hostID, timestamp);
- }
- migdPtr->info.loadVec.timestamp = timestamp;
- if (migdPtr->info.state != MIG_HOST_DOWN) {
- panic("RestoreCheckPoint: host was not in DOWN state before.\n");
- }
- hostsRead++;
- }
- if (global_Debug > 1) {
- fprintf(stderr, "\n%x: RestoreCheckPoint - read %d hosts.\n",
- migd_Pid, hostsRead);
- }
- (void) fclose(checkPoint);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * SaveCheckPoint --
- *
- * Save the last known state of the world to a checkpoint
- * file. While we're at it, check for hosts we haven't heard from
- * in a while, and check to make sure we're still controlling the
- * real master pdev (someone else could have mistakenly removed it
- * and started a second master, and new contacts would reach it instead
- * of this process).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Hosts may be marked as DOWN.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static void
- SaveCheckPoint(clientData, timeArg)
- ClientData clientData; /* Generic callback arg, not used. */
- Time timeArg; /* Generic callback arg, not used. */
- {
- FILE *checkPoint;
- Migd_Info *migdPtr;
- int i;
- struct timeval tv;
- int status;
- struct stat nameAtts;
-
- if (global_Debug > 1) {
- int t = time(0);
- PRINT_PID;
- fprintf(stderr, "Global daemon checkpoint: running on %s at %s",
- migd_HostName, ctime(&t));
- }
-
- #ifdef 0
- if (lstat(migd_GlobalPdevName, &nameAtts) < 0) {
- SYSLOG2(LOG_ERR, "Exiting: unable to stat %s: %s.\n",
- migd_GlobalPdevName, strerror(errno));
- exit(1);
- }
- #endif
- if (lstat(MIGD_LOCK_FILE, &nameAtts) < 0) {
- SYSLOG2(LOG_ERR, "Exiting: unable to stat %s: %s.\n",
- MIGD_LOCK_FILE, strerror(errno));
- exit(1);
- }
- if (nameAtts.st_ino != descAtts.st_ino ||
- nameAtts.st_version != descAtts.st_version) {
- SYSLOG3(LOG_WARNING,
- "Exiting: mismatch statting files: name inode <%d,%d>, version %d.\n",
- nameAtts.st_ino, nameAtts.st_devServerID, nameAtts.st_version);
- SYSLOG3(LOG_WARNING,
- "\tdescriptor inode <%d,%d> version %d (another migd running, or server changed file version).\n",
- descAtts.st_ino, descAtts.st_devServerID, descAtts.st_version);
- exit(1);
- }
-
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "Descriptors matched okay.\n");
- }
-
-
- checkPoint = fopen(MIGD_CHECKPOINT_FILE, "w+");
- if (checkPoint == (FILE *) NULL) {
- SYSLOG1(LOG_WARNING, "SaveCheckPoint - error writing checkpoint: %s.\n",
- strerror(errno));
- return;
- }
- status = gettimeofday(&tv, (struct timezone *) NULL);
- if (status == -1) {
- SYSLOG1(LOG_ERR, "Error in gettimeofday: %s", strerror(errno));
- exit(1);
- }
-
- if (migd_DoStats) {
- DumpStats(checkPoint);
- }
-
- for (i = 1; i <= maxKnownHost; i++) {
- migdPtr = migInfoArray[i];
- if (migdPtr == (Migd_Info *) NULL ||
- migdPtr->info.loadVec.timestamp == 0) {
- continue;
- }
- if (fprintf(checkPoint, "%d %d\n", migdPtr->info.hostID,
- migdPtr->info.loadVec.timestamp) < 0) {
- SYSLOG1(LOG_WARNING,
- "SaveCheckPoint - error writing record to checkpoint file: %s.\n",
- strerror(errno));
- if (global_Debug == 0) {
- (void) unlink(MIGD_CHECKPOINT_FILE);
- }
- }
- if (migdPtr->info.state != MIG_HOST_DOWN &&
- migdPtr->info.loadVec.timestamp < tv.tv_sec - MIG_TIMEOUT) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "SaveCheckPoint - marking %s down (curTime %d, updated %d).\n",
- migdPtr->name, tv.tv_sec,
- migdPtr->info.loadVec.timestamp);
- }
- (void) Global_HostDown(i, 0);
- } else if (migdPtr->info.loadVec.foreignProcs == 0 &&
- migdPtr->info.loadVec.allowMigration &&
- (migdPtr->info.state == MIG_HOST_PART_USED ||
- migdPtr->info.state == MIG_HOST_FULL)) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "SaveCheckPoint - checking %s foreign count.\n",
- migdPtr->name);
- }
-
- if (migdPtr->flags & MIGD_WAS_EMPTY) {
- ForceHostIdle(migdPtr);
- } else {
- migdPtr->flags |= MIGD_WAS_EMPTY;
- }
- }
- }
- fflush(checkPoint);
- if (fsync(fileno(checkPoint)) < 0) {
- SYSLOG0(LOG_WARNING, "Error syncing checkpoint file to disk.\n");
- }
- (void) fclose(checkPoint);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DumpStats --
- *
- * Write statistics out in ASCII to the checkpoint file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- DumpStats(file)
- FILE *file;
- {
- int i, j;
-
- global_Stats.intervals++;
-
- fprintf(file, "%% Version %u HasStats %u Interval %u last run on %s.\n",
- migd_Version, migd_DoStats, global_CheckpointInterval,
- migd_HostName);
- fprintf(file, "%% firstRun %u\n", global_Stats.firstRun);
- fprintf(file, "%% restarts %u\n", global_Stats.restarts);
- fprintf(file, "%% intervals %u\n", global_Stats.intervals);
- fprintf(file, "%% maxArchs %u\n", global_Stats.maxArchs);
- fprintf(file, "%% getLoadRequests %u\n", global_Stats.getLoadRequests);
- fprintf(file, "%% totalRequests %u\n", global_Stats.totalRequests);
- fprintf(file, "%% totalObtained %u\n", global_Stats.totalObtained);
- fprintf(file, "%% numRepeatRequests %u\n", global_Stats.numRepeatRequests);
- fprintf(file, "%% numRepeatAssignments %u\n",
- global_Stats.numRepeatAssignments);
- fprintf(file, "%% numFirstAssignments %u\n",
- global_Stats.numFirstAssignments);
- for (i = 0; i < global_Stats.maxArchs; i++) {
- fprintf(file, "%% arch %u %s\n",
- i, global_Stats.archStats[i].arch);
- fprintf(file, "%% \tnumClients %u\n",
- global_Stats.archStats[i].numClients);
- fprintf(file, "%% \tgotAll %u\n",
- global_Stats.archStats[i].gotAll);
- fprintf(file, "%% \tnonIdleTransitions %u\n",
- global_Stats.archStats[i].nonIdleTransitions);
-
- fprintf(file, "%% \trequested %u %u\n",
- global_Stats.archStats[i].counters.requested,
- global_Stats.archStats[i].squared.requested);
- fprintf(file, "%% \tobtained %u %u\n",
- global_Stats.archStats[i].counters.obtained,
- global_Stats.archStats[i].squared.obtained);
- fprintf(file, "%% \tevicted %u %u\n",
- global_Stats.archStats[i].counters.evicted,
- global_Stats.archStats[i].squared.evicted);
- fprintf(file, "%% \treclaimed %u %u\n",
- global_Stats.archStats[i].counters.reclaimed,
- global_Stats.archStats[i].squared.reclaimed);
- fprintf(file, "%% \ttimeUsed %u %u\n",
- global_Stats.archStats[i].counters.timeUsed,
- global_Stats.archStats[i].squared.timeUsed);
- fprintf(file, "%% \ttimeToEviction %u %u\n",
- global_Stats.archStats[i].counters.timeToEviction,
- global_Stats.archStats[i].squared.timeToEviction);
- fprintf(file, "%% \thostIdleObtained %u %u %u %u\n",
- global_Stats.archStats[i].counters.hostIdleObtained[MIG_COUNTER_HIGH],
- global_Stats.archStats[i].counters.hostIdleObtained[MIG_COUNTER_LOW],
- global_Stats.archStats[i].squared.hostIdleObtained[MIG_COUNTER_HIGH],
- global_Stats.archStats[i].squared.hostIdleObtained[MIG_COUNTER_LOW]);
- fprintf(file, "%% \thostIdleEvicted %u %u %u %u\n",
- global_Stats.archStats[i].counters.hostIdleEvicted[MIG_COUNTER_HIGH],
- global_Stats.archStats[i].counters.hostIdleEvicted[MIG_COUNTER_LOW],
- global_Stats.archStats[i].squared.hostIdleEvicted[MIG_COUNTER_HIGH],
- global_Stats.archStats[i].squared.hostIdleEvicted[MIG_COUNTER_LOW]);
- fprintf(file, "%% \tidleTimeWhenActive %u %u %u %u\n",
- global_Stats.archStats[i].counters.idleTimeWhenActive[MIG_COUNTER_HIGH],
- global_Stats.archStats[i].counters.idleTimeWhenActive[MIG_COUNTER_LOW],
- global_Stats.archStats[i].squared.idleTimeWhenActive[MIG_COUNTER_HIGH],
- global_Stats.archStats[i].squared.idleTimeWhenActive[MIG_COUNTER_LOW]);
-
- fprintf(file, "%% \trequestDist ");
- for (j = 0; j <= MIG_MAX_HOSTS_DIST; j++) {
- fprintf(file, "%u ",
- global_Stats.archStats[i].requestDist[j]);
- }
- fprintf(file, "\n");
-
- fprintf(file, "%% \tobtainedDist ");
- for (j = 0; j <= MIG_MAX_HOSTS_DIST; j++) {
- fprintf(file, "%u ",
- global_Stats.archStats[i].obtainedDist[j]);
- }
- fprintf(file, "\n");
-
- fprintf(file, "%% \thostCounts ");
- for (j = 0; j < MIG_NUM_STATES; j++) {
- global_Stats.archStats[i].counters.hostCounts[j] +=
- hostCounts[i][j];
- global_Stats.archStats[i].squared.hostCounts[j] +=
- hostCounts[i][j] * hostCounts[i][j];
- fprintf(file, "%u %u ",
- global_Stats.archStats[i].counters.hostCounts[j],
- global_Stats.archStats[i].squared.hostCounts[j]);
- }
- fprintf(file, "\n");
- }
- fprintf(file, "%% End of Statistics\n");
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * ReadStats --
- *
- * Read statistics in ASCII format from the checkpoint file.
- *
- * Results:
- * If we are the wrong version, or we hit some error, we return -1.
- * That indicates that the caller should just ignore any subsequent
- * lines with "%" in them. 0 indicates success.
- *
- * Side effects:
- * Statistics are reset from last checkpoint.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- ReadStats(file)
- FILE *file;
- {
- int i, j;
- int numScanned;
- char buffer[BUFSIZ];
- int lineNum = 0;
- int lastVersion; /* Version of migd that wrote checkpoint. */
- int lastInterval; /* Checkpoint interval of migd that wrote
- checkpoint. */
- int didStats; /* Whether that migd wrote the statistics. */
- int maxArchs; /* Value of global_Stats.maxArchs for that
- migd. */
- int archNum; /* Index into archTypes array. */
- char archName[BUFSIZ]; /* Temporary buffer for name, to compare
- against our index. */
-
- /*
- * Common action to take on bad input.
- */
- #define BAD_INPUT \
- if (global_Debug > 1) { \
- PRINT_PID; \
- fprintf(stderr, \
- "ReadStats: bad input on line %d: %s", \
- lineNum, buffer); \
- } \
- return(-1);
-
-
-
- /*
- * For each line, read the whole thing into a buffer (1) to make sure
- * it starts with "%" and (2) to be able to print it out entirely
- * if there's a problem.
- */
- #define READLINE \
- if (fgets(buffer, sizeof(buffer), file) == (char *) NULL) { \
- if (global_Debug > 1) { \
- PRINT_PID; \
- fprintf(stderr, \
- "ReadStats: end of file at line %d.\n", lineNum); \
- } \
- return(-1); \
- } \
- lineNum++; \
- if (buffer[0] != '%') { \
- BAD_INPUT; \
- }
-
- READLINE;
-
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "ReadStats: %s", buffer);
- }
-
- numScanned = sscanf(buffer, "%% Version %u HasStats %u Interval %u",
- &lastVersion, &didStats, &lastInterval);
- if (numScanned != 3) {
- BAD_INPUT;
- }
- if (lastVersion != migd_Version ||
- lastInterval != global_CheckpointInterval) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: mismatch in migd versions or intervals: ours is %u, %u but last writer\n\tof checkpoint was %u, %u.\n",
- migd_Version, global_CheckpointInterval,
- lastVersion, lastInterval);
- }
- return(-1);
- }
- if (didStats != 1) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: last writer of checkpoint didn't do stats.\n");
- }
- return(0);
- }
-
-
- READLINE;
- numScanned = sscanf(buffer, "%% firstRun %u", &global_Stats.firstRun);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% restarts %u", &global_Stats.restarts);
- if (numScanned != 1) {
- BAD_INPUT;
- }
- global_Stats.restarts++;
-
- READLINE;
- numScanned = sscanf(buffer, "%% intervals %u", &global_Stats.intervals);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% maxArchs %u", &maxArchs);
- if (numScanned != 1) {
- BAD_INPUT;
- }
- if (maxArchs != global_Stats.maxArchs) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: discrepancy in number of architectures managed by\n\tmigd; resetting statistics.\n");
- }
- return(-1);
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% getLoadRequests %u",
- &global_Stats.getLoadRequests);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% totalRequests %u",
- &global_Stats.totalRequests);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% totalObtained %u",
- &global_Stats.totalObtained);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% numRepeatRequests %u",
- &global_Stats.numRepeatRequests);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% numRepeatAssignments %u",
- &global_Stats.numRepeatAssignments);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% numFirstAssignments %u",
- &global_Stats.numFirstAssignments);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- for (i = 0; i < maxArchs; i++) {
- READLINE;
- numScanned = sscanf(buffer, "%% arch %u %s", &archNum, archName);
- if (numScanned != 2) {
- BAD_INPUT;
- }
- if (archNum != i || strcmp(archName, global_Stats.archStats[i].arch)) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% \tnumClients %u",
- &global_Stats.archStats[i].numClients);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% \tgotAll %u",
- &global_Stats.archStats[i].gotAll);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% \tnonIdleTransitions %u",
- &global_Stats.archStats[i].nonIdleTransitions);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% \trequested %u %u",
- &global_Stats.archStats[i].counters.requested,
- &global_Stats.archStats[i].squared.requested);
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \tobtained %u %u",
- &global_Stats.archStats[i].counters.obtained,
- &global_Stats.archStats[i].squared.obtained);
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \tevicted %u %u",
- &global_Stats.archStats[i].counters.evicted,
- &global_Stats.archStats[i].squared.evicted);
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \treclaimed %u %u",
- &global_Stats.archStats[i].counters.reclaimed,
- &global_Stats.archStats[i].squared.reclaimed);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \ttimeUsed %u %u",
- &global_Stats.archStats[i].counters.timeUsed,
- &global_Stats.archStats[i].squared.timeUsed);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \ttimeToEviction %u %u",
- &global_Stats.archStats[i].counters.timeToEviction,
- &global_Stats.archStats[i].squared.timeToEviction);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \thostIdleObtained %u %u %u %u",
- &global_Stats.archStats[i].counters.hostIdleObtained[MIG_COUNTER_HIGH],
- &global_Stats.archStats[i].counters.hostIdleObtained[MIG_COUNTER_LOW],
- &global_Stats.archStats[i].squared.hostIdleObtained[MIG_COUNTER_HIGH],
- &global_Stats.archStats[i].squared.hostIdleObtained[MIG_COUNTER_LOW]);
-
- if (numScanned != 4) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \thostIdleEvicted %u %u %u %u",
- &global_Stats.archStats[i].counters.hostIdleEvicted[MIG_COUNTER_HIGH],
- &global_Stats.archStats[i].counters.hostIdleEvicted[MIG_COUNTER_LOW],
- &global_Stats.archStats[i].squared.hostIdleEvicted[MIG_COUNTER_HIGH],
- &global_Stats.archStats[i].squared.hostIdleEvicted[MIG_COUNTER_LOW]);
-
- if (numScanned != 4) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \tidleTimeWhenActive %u %u %u %u",
- &global_Stats.archStats[i].counters.idleTimeWhenActive[MIG_COUNTER_HIGH],
- &global_Stats.archStats[i].counters.idleTimeWhenActive[MIG_COUNTER_LOW],
- &global_Stats.archStats[i].squared.idleTimeWhenActive[MIG_COUNTER_HIGH],
- &global_Stats.archStats[i].squared.idleTimeWhenActive[MIG_COUNTER_LOW]);
- if (numScanned != 4) {
- BAD_INPUT;
- }
- /*
- * No easy way to use sscanf to go through a string piece
- * by piece, so use fscanf. First for distribution of requests,
- * then count of hosts.
- */
- numScanned = fscanf(file, "%% \trequestDist");
- if (numScanned < 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning requestDist line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- for (j = 0; j <= MIG_MAX_HOSTS_DIST; j++) {
- numScanned = fscanf(file, "%u ",
- &global_Stats.archStats[i].requestDist[j]);
- if (numScanned != 1) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning requestDist line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- }
- numScanned = fscanf(file, "\n");
- if (numScanned < 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning requestDist line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- lineNum++;
-
- numScanned = fscanf(file, "%% \tobtainedDist");
- if (numScanned < 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning obtainedDist line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- for (j = 0; j <= MIG_MAX_HOSTS_DIST; j++) {
- numScanned = fscanf(file, "%u ",
- &global_Stats.archStats[i].obtainedDist[j]);
- if (numScanned != 1) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning obtainedDist line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- }
- numScanned = fscanf(file, "\n");
- if (numScanned < 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning obtainedDist line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- lineNum++;
-
- numScanned = fscanf(file, "%% \thostCounts");
- if (numScanned < 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning hostCounts line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- for (j = 0; j < MIG_NUM_STATES; j++) {
- numScanned = fscanf(file, "%u %u ",
- &global_Stats.archStats[i].counters.hostCounts[j],
- &global_Stats.archStats[i].squared.hostCounts[j]);
- if (numScanned != 2) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning hostCounts line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- }
- numScanned = fscanf(file, "\n");
- if (numScanned < 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr,
- "ReadStats: error scanning hostCounts line (%d).\n",
- lineNum);
- }
- return(-1);
- }
- lineNum++;
- }
- return(0);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * CltToMigd --
- *
- * Return the migd pointer corresponding to a host, given its
- * cltPtr. This combines all the sanity checks in a single
- * location.
- *
- * Results:
- * A pointer to the internal Migd_Info record for the host is returned,
- * or NULL if the entry doesn't exist.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static Migd_Info *
- CltToMigd(cltPtr)
- Migd_OpenStreamInfo *cltPtr;
- {
- Migd_Info *migdPtr;
-
- migdPtr = migInfoArray[cltPtr->host];
- if (migdPtr == (Migd_Info *) NULL) {
- return((Migd_Info *) NULL);
- }
- if (migdPtr->cltPtr != cltPtr) {
- SYSLOG1(LOG_WARNING,
- "Mismatch in client information for host %d.\n", cltPtr->host);
- return((Migd_Info *) NULL);
- }
- return(migdPtr);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * HostIsIdle --
- *
- * Return whether a host is considered to be at least partly
- * idle. This should be changed to a macro once debugging is over.
- *
- * Results:
- * A non-zero value is returned if the host referenced by migdPtr
- * is considered to be idle, else 0.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- HostIsIdle(migdPtr)
- Migd_Info *migdPtr;
- {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "HostIsIdle: %s was ", migdPtr->name);
- }
- if (migdPtr->info.state == MIG_HOST_IDLE ||
- migdPtr->info.state == MIG_HOST_PART_USED) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "idle\n");
- }
- return(1);
- }
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "not idle\n");
- }
- return(0);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * ForceHostIdle --
- *
- * Restore sanity to a host by removing all indications of clients
- * associated with the host and then putting it back on the idle list.
- * This is necessary if, for example, someone requests a host
- * and then doesn't release it.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Host is put on idle list.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- ForceHostIdle(migdPtr)
- Migd_Info *migdPtr;
- {
- List_Links *listPtr;
- RequestInfo *reqPtr;
-
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "ForceHostIdle: %s now believed to be idle.\n",
- migdPtr->name);
- }
- while (!List_IsEmpty(&migdPtr->clientList)) {
- listPtr = List_First(&migdPtr->clientList);
- List_Remove(listPtr);
- reqPtr = NEXT_HOST_REQUEST_TO_INFO(listPtr);
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Removing request from process %x.\n",
- (reqPtr->flags & MIG_PROC_AGENT) ?
- reqPtr->client.processID :
- reqPtr->client.cltPtr->processID);
- }
- /*
- * This is like an eviction, except no processes are getting evicted
- * -- we don't even think there are any there. Instead, we notify
- * the client that we've revoked its permission to use this host
- * later on.
- */
- RevokePermission(reqPtr, REVOKE_IDLE);
- free((char *) reqPtr);
- }
- migdPtr->flags &= ~(MIGD_CHECK_COUNT | MIGD_WAS_EMPTY);
- if (HostIsIdle(migdPtr)) {
- List_Remove((List_Links *) migdPtr);
- }
- InsertIdle(migdPtr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_GetStats --
- *
- * Return the statistics structure to a user process.
- *
- * Results:
- * 0 for success, or an errno indicating the error.
- * The statistics, and the size of the buffer, are returned.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_GetStats(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Not used. */
- int inBufSize; /* Not used. */
- char *outBuffer; /* Buffer to place results. */
- int *outBufSizePtr; /* Size of the output buffer. */
- {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Global_GetStats called.\n");
- }
-
- if (*outBufSizePtr != sizeof(Mig_Stats)) {
- if (global_Debug > 0) {
- SYSLOG3(LOG_WARNING,
- "Global_GetStats: bad output buffer size (%d, not %d) from process %x\n",
- *outBufSizePtr, sizeof(Mig_Stats), cltPtr->processID);
- }
- return(EINVAL);
- }
- bcopy((char *) &global_Stats, outBuffer, sizeof(Mig_Stats));
- return(0);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_ResetStats --
- *
- * Reinitialize the statistics structure to a user process. This
- * is just a stub that takes standard ioctl arguments and calls the
- * internal routine.
- *
- * Results:
- * 0 indicates success.
- *
- * Side effects:
- * Statistics are zeroed.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_ResetStats(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Not used. */
- int inBufSize; /* Not used. */
- char *outBuffer; /* Buffer to place results. */
- int *outBufSizePtr; /* Size of the output buffer. */
- {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Global_ResetStats called.\n");
- }
-
- InitStats();
-
- return(0);
- }
-
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_SetParms --
- *
- * Set the parameters used by all migration daemons.
- *
- * Results:
- * 0 for success, or an errno indicating the error.
- *
- * Side effects:
- * Host-specific daemon connections are made readable so
- * they know to perform an ioctl to get the info.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- int
- Global_SetParms(cltPtr, command, inBuffer, inBufSize, outBuffer,
- outBufSizePtr)
- Migd_OpenStreamInfo *cltPtr;/* Information about the client making
- the request. */
- int command; /* Ignored. */
- char *inBuffer; /* Buffer to get arguments from. */
- int inBufSize; /* Size of the input buffer. */
- char *outBuffer; /* Buffer to place results, not used. */
- int *outBufSizePtr; /* Size of the output buffer, set to 0. */
- {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Global_SetParms called.\n");
- }
-
- /*
- * XXX need to add this here.
- */
- return(EINVAL);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Global_DumpIdleList --
- *
- * For debugging purposes: print an idle list, given the header.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Global_DumpIdleList(hdrPtr)
- List_Links *hdrPtr;
- {
- List_Links *itemPtr;
- Migd_Info *migdPtr;
-
- LIST_FORALL(hdrPtr, itemPtr) {
- migdPtr = (Migd_Info *) itemPtr;
- fprintf(stderr, "\t%s idle %d seconds\n", migdPtr->name,
- migdPtr->info.loadVec.noInput);
- }
- fflush(stderr);
- }
-
-
- @
-
-
- 2.4
- log
- @use multiple waiting lists, 1 per priority level
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 2.3 90/09/14 14:05:45 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d2356 1
- @
-
-
- 2.3
- log
- @a few changes to fix bugs and to log instantiations of migd in a separate log
- file.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 2.2 90/07/05 18:35:27 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d152 2
- a153 1
- static List_Links *waitingLists; /* array of lists of waiting clients,
- d356 2
- d361 1
- a363 4
- waitingLists = (List_Links *) Malloc(maxArchTypes * sizeof(List_Links));
- for (j = 0; j < maxArchTypes; j++) {
- List_Init(&waitingLists[j]);
- }
- d1027 1
- a1027 1
- List_Links *waitingList = &waitingLists[archType];
- d1635 3
- a1637 2
- * processes waiting for available hosts and let them ask again.
- * Wakes up only processes of a particular archType.
- d1652 1
- a1652 1
- List_Links *waitingList = &waitingLists[archType];
- d1658 2
- d1668 33
- a1700 16
- while (!List_IsEmpty(waitingList)) {
- /*
- * For each process waiting, get rid of the info saying it's waiting
- * and instead add a message to the process.
- */
- listPtr = List_First(waitingList);
- waitPtr = (Migd_WaitList *) listPtr;
- List_Remove(listPtr);
- cltPtr = waitPtr->cltPtr;
- cltPtr->waitPtr = (Migd_WaitList *) NULL;
- if (cltPtr->stoleTime > curTime - MIGD_STOLE_WINDOW) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "\t** not telling process %x about host available, since we stole from it recently.\n",
- cltPtr->processID);
- a1701 8
- } else {
- TellClient(cltPtr, 0);
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "\t** telling process %x about host available.\n",
- cltPtr->processID);
- }
- a1702 1
- free((char *) waitPtr);
- a1703 1
-
- @
-
-
- 2.2
- log
- @increment stats for reclaimed hosts
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 2.1 90/07/05 13:19:25 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d182 4
- d245 1
- d308 16
- d942 1
- d1202 1
- a1202 1
- if (global_Debug > 2) {
- d1205 2
- a1206 2
- "CheckFairness evicting processes on host %d.\n",
- bestReqPtr->migdPtr->info.hostID);
- d1212 1
- a1212 1
- List_Remove(bestReqPtr->migdPtr);
- d1761 1
- a1761 15
- if (!(reqPtr->flags & MIG_PROC_AGENT)) {
- RevokePermission(reqPtr, REVOKE_EVICT);
- } else {
- /*
- * Request was on behalf of another process, so we don't
- * increment the client numEvicted field and instead add it
- * in to the totals independently. (For regular clients we
- * accumulate multiple evictions/client and then the "squared"
- * statistic weights clustered evictions.)
- */
- if (migd_DoStats) {
- global_Stats.archStats[migdPtr->archType].counters.evicted++;
- global_Stats.archStats[migdPtr->archType].squared.evicted++;
- }
- }
- d1863 8
- d1897 12
- a1909 1
- List_Remove(&reqPtr->nextInUse);
- d2700 18
- a2717 6
- migdPtr->info.state == MIG_HOST_PART_USED) &&
- oldForeign > 0 && vecPtr->foreignProcs == 0) {
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "\t--%s now has no foreigners--\n",
- migdPtr->name);
- a2718 1
- ForceHostIdle(migdPtr);
- @
-
-
- 2.1
- log
- @added fairness considerations, and moved around some code.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 2.0 90/06/30 17:06:57 douglis Stable Locker: douglis $ SPRITE (Berkeley)";
- d1458 3
- d1868 12
- @
-
-
- 2.0
- log
- @Changing version numbers.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.14 90/06/30 17:06:07 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d78 1
- a78 1
- * clients.
- d82 1
- a82 1
- int hostID; /* Host to tell client about. */
- d96 2
- d116 20
- d149 3
- d204 3
- d332 2
- d336 1
- d629 1
- a629 1
- Mig_InfoRequest *requestPtr;/* Request from client. */
- d654 3
- a656 3
- requestPtr = (Mig_InfoRequest *) inBuffer;
- firstHost = requestPtr->firstHost;
- numRecs = requestPtr->numRecs;
- d741 1
- a741 1
- Mig_IdleRequest *requestPtr;/* Request from client. */
- d761 1
- d771 2
- a772 2
- requestPtr = (Mig_IdleRequest *) inBuffer;
- numHosts = requestPtr->numHosts;
- d795 1
- a795 1
- priority = requestPtr->priority;
- d838 2
- d841 2
- a842 2
- tryPrio = MIG_LOW_PRIORITY;
- outPtr = (int *) (outBuffer + sizeof(int));
- d844 8
- a851 14
- while (total < numHosts && tryPrio <= priority) {
- idleList = &idleHostsArray[tryPrio][archType];
- nextPtr = List_First(idleList);
- while (total < numHosts && !List_IsAtEnd(idleList, nextPtr)) {
- listPtr = nextPtr;
- nextPtr = List_Next(nextPtr);
- migdPtr = (Migd_Info *) listPtr;
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr, "Examining %s.\n",
- migdPtr->name);
- }
- if (migdPtr->info.hostID == requestPtr->virtHost ||
- migdPtr->info.hostID == cltPtr->host) {
- d854 21
- a874 2
- fprintf(stderr, "Skipping over %s.\n",
- migdPtr->name);
- d876 19
- a894 9
- continue;
- }
- if (migdPtr->info.migVersion != migVersion) {
- if (global_Debug > 3) {
- PRINT_PID;
- fprintf(stderr,
- "Migration version mismatch: %s version %d, %s version %d.\n",
- migdPtr->name, migdPtr->info.migVersion,
- reqMigdPtr->name, migVersion);
- a895 5
- continue;
- }
- infoPtr = (Mig_Info *) &migdPtr->info;
- infoPtr->foreign[priority]++;
- if (infoPtr->foreign[priority] >= infoPtr->maxProcs) {
- d897 8
- a904 3
- * Used up all the processors on this host for processes
- * of this type, so put the host on the queue for
- * the next higher priority.
- d906 11
- a916 7
- List_Remove(listPtr);
- hostCounts[archType][infoPtr->state]--;
- if (priority < MIG_HIGH_PRIORITY) {
- List_Insert(listPtr,
- LIST_ATREAR(&idleHostsArray
- [priority + 1][archType]));
- infoPtr->state = MIG_HOST_PART_USED;
- d918 2
- a919 1
- infoPtr->state = MIG_HOST_FULL;
- d921 28
- a948 29
- hostCounts[archType][infoPtr->state]++;
- }
- /*
- * Allocate a new request info structure and set it up
- * so we can find this request via the host's record or via the
- * client process. Only chain it to the client process if
- * it isn't an "agent" request, since we reclaim hosts on the
- * client's chain of requests when the connection is closed.
- *
- * XXX We'd like to assign multiple processors in a single shot
- * here...
- */
- reqPtr = mnew(RequestInfo);
- reqPtr->priority = priority;
- reqPtr->migdPtr = migdPtr;
- reqPtr->flags = requestPtr->flags;
- reqPtr->idleTime = migdPtr->info.loadVec.noInput;
- reqPtr->numProcessors = 1;
- if (! (reqPtr->flags & MIG_PROC_AGENT)) {
- reqPtr->client.cltPtr = cltPtr;
- List_InitElement(&reqPtr->nextClientRequest);
- List_Insert(&reqPtr->nextClientRequest,
- LIST_ATREAR(&cltPtr->currentRequests));
- } else {
- reqPtr->client.processID = cltPtr->processID;
- migdPtr->flags |= MIGD_CHECK_COUNT;
- }
- if (migd_DoStats) {
- int noInput;
- d950 6
- a955 15
- global_Stats.totalObtained++;
- noInput = (infoPtr->loadVec.noInput + 30) / 60 ;
- reqPtr->timestamp = time(0);
- reqPtr->idleTime = noInput;
- ADD_WITH_OVERFLOW(archPtr->counters.hostIdleObtained, noInput);
- ADD_WITH_OVERFLOW(archPtr->squared.hostIdleObtained,
- noInput * noInput);
- /*
- * Is this host being assigned to the last host that was
- * using it?
- */
- if (migdPtr->lastHostAssigned == cltPtr->host) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "\t** Repeat assignment:\n");
- d957 1
- a957 7
- global_Stats.numRepeatAssignments++;
- } else if (migdPtr->lastHostAssigned == -1) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "\t** First assignment to host:\n");
- }
- global_Stats.numFirstAssignments++;
- a958 1
- migdPtr->lastHostAssigned = cltPtr->host;
- d960 3
- a962 9
- if (cltPtr->host == lastRequestHost) {
- if (global_Debug > 4) {
- PRINT_PID;
- fprintf(stderr, "\t** Repeat requesting host:\n");
- }
- global_Stats.numRepeatRequests++;
- }
- lastRequestHost = cltPtr->host;
- }
- d964 3
- a966 3
- List_InitElement(&reqPtr->nextHostRequest);
- List_Insert(&reqPtr->nextHostRequest,
- LIST_ATREAR(&migdPtr->clientList));
- d968 15
- a982 8
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "\t** Assigning %s to process %x.\n",
- migdPtr->name, cltPtr->processID);
- }
- total++;
- *outPtr = infoPtr->hostID;
- outPtr++;
- d984 1
- a984 1
- tryPrio++;
- d996 8
- d1019 156
- a1174 1
-
- d1176 1
- a1176 2
- * XXX Would like to record some per-user summary info here for fairness
- * policy issues. But record per-process in any case.
- d1178 13
- a1190 6
-
- cltPtr->numInUse += total;
- if (migd_DoStats) {
- cltPtr->numObtained += total;
- if (cltPtr->numInUse > cltPtr->maxObtained) {
- cltPtr->maxObtained = cltPtr->numInUse;
- d1192 3
- a1195 2
-
-
- a1196 1
-
- d1267 1
- a1267 2
- * If a specific host is specified and the host is not being used by
- * the client, EINVAL is returned, else 0.
- a1328 3
- if (host != MIG_ALL_HOSTS) {
- returnCode = EINVAL;
- }
- d1361 2
- d1409 1
- a1409 1
- if (msgPtr->hostID == host || host == MIG_ALL_HOSTS) {
- d1440 3
- a1442 2
- "Global_Done: process %x had a max of %d requests, %d obtained.\n",
- cltPtr->processID, requests, obtained);
- d1467 3
- a1469 5
- /*
- * XXX Would have to modify per-user summary info here for fairness
- * policy issues.
- */
-
- d1631 1
- d1639 1
- d1650 15
- a1664 6
- TellClient(cltPtr, 0);
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "\t** telling process %x about host available.\n",
- cltPtr->processID);
- d1737 1
- a1737 7
- /*
- * Remove it from the user's list.
- */
- List_Remove((List_Links *) reqPtr);
- cltPtr = reqPtr->client.cltPtr;
- TellClient(cltPtr, migdPtr->info.hostID);
- cltPtr->numEvicted++;
- d1802 1
- a1802 1
- TellClient(cltPtr, hostID)
- d1804 1
- a1804 1
- int hostID; /* ID of host, or 0. */
- d1808 6
- d1816 1
- a1816 1
- msgPtr->hostID = hostID;
- d1827 47
- d1935 1
- a1935 1
- *intPtr = msgPtr->hostID;
- d1938 6
- d2024 1
- a2024 1
- int hostID;
- d2080 1
- a2080 1
- int hostID;
- d3563 7
- a3569 5
- if (!(reqPtr->flags & MIG_PROC_AGENT)) {
- List_Remove((List_Links *) reqPtr);
- migdPtr->info.foreign[reqPtr->priority] -= reqPtr->numProcessors;
- TellClient(reqPtr->client.cltPtr, migdPtr->info.hostID);
- }
- @
-
-
- 1.14
- log
- @mostly simplifications & moving common code to subroutines.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.13 90/06/26 22:09:03 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- @
-
-
- 1.13
- log
- @handle case when eviction comes after change back to availability.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.12 90/05/28 17:06:38 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d165 15
- a179 13
- static void CreateMigdRecord(); /* allocate a Migd_Info record. */
- static void RestoreCheckPoint(); /* restore checkpoint from file */
- static void SaveCheckPoint(); /* save checkpoint to file */
- static void CheckHostStatus(); /* check the status of a host after an
- update */
- static int RemoveHost(); /* remove host from list of hosts */
- static int HostIsIdle(); /* check for host being idle */
- static void InsertIdle(); /* add host to list of idle hosts */
- static void WakeupWaiters(); /* wake up processes that want more hosts. */
- static void RecordEvictions(); /* remove host from idle list and notify
- clients of evictions */
- static void ForceHostIdle(); /* make a host seem idle */
- static Migd_Info *CltToMigd(); /* map from client info to migd record */
- d1436 1
- a1436 3
- msgPtr = mnew(MessageBlock);
- List_InitElement(&msgPtr->links);
- msgPtr->hostID = 0;
- a1442 4
- if (List_IsEmpty(&cltPtr->messages)) {
- MigPdev_MakeReady(cltPtr->streamPtr, (ClientData) NULL);
- }
- List_Insert((List_Links *) msgPtr, LIST_ATREAR(&cltPtr->messages));
- a1476 1
- MessageBlock *msgPtr;
- a1517 3
- /*
- * XXX Remigrate outstanding processes here, someday.
- */
- d1519 1
- a1519 7
- msgPtr = mnew(MessageBlock);
- List_InitElement(&msgPtr->links);
- msgPtr->hostID = migdPtr->info.hostID;
- if (List_IsEmpty(&cltPtr->messages)) {
- MigPdev_MakeReady(cltPtr->streamPtr, (ClientData) NULL);
- }
- List_Insert((List_Links *) msgPtr, LIST_ATREAR(&cltPtr->messages));
- d1564 35
- d3290 1
- @
-
-
- 1.12
- log
- @stats changes, plus bug fix for reopening unclosed connection over and over.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.11 90/05/14 21:32:59 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d2366 15
- @
-
-
- 1.11
- log
- @bug fixes, including List_Remove bug resulting from state not being set
- properly.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.10 90/05/03 11:17:32 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d793 1
- d887 1
- d903 7
- a909 1
- archPtr->numRepeatAssignments++;
- d918 1
- a918 1
- archPtr->numRepeatRequests++;
- a1980 2
- cltPtr->type = MIGD_DAEMON;
- cltPtr->defaultSelBits = FS_WRITE;
- d2082 13
- a2094 1
- migdPtr->info = *infoPtr;
- d2106 1
- d2108 2
- a2113 9
- if (infoPtr->state == MIG_HOST_IDLE && !infoPtr->loadVec.allowMigration) {
- if (global_Debug > 0) {
- PRINT_PID;
- fprintf(stderr,
- "Host %s marked as idle but not allowing migration.\n",
- migdPtr->name);
- }
- migdPtr->info.state = MIG_HOST_REFUSES;
- }
- d2116 1
- a2116 1
- if (migdPtr->info.state == MIG_HOST_IDLE) {
- a2185 6
- if (global_Debug > 1) {
- PRINT_PID;
- fprintf(stderr, "Global_HostDown(host=%d, closed=%d) called.\n",
- hostID, closed);
- }
-
- d2194 6
- d2650 7
- a2663 6
- fprintf(file, "%% \tnumRepeatRequests %u\n",
- global_Stats.archStats[i].numRepeatRequests);
- fprintf(file, "%% \tnumRepeatAssignments %u\n",
- global_Stats.archStats[i].numRepeatAssignments);
- fprintf(file, "%% \tnumFirstAssignments %u\n",
- global_Stats.archStats[i].numFirstAssignments);
- d2871 36
- a2930 21
- READLINE;
- numScanned = sscanf(buffer, "%% \tnumRepeatRequests %u",
- &global_Stats.archStats[i].numRepeatRequests);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% \tnumRepeatAssignments %u",
- &global_Stats.archStats[i].numRepeatAssignments);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- READLINE;
- numScanned = sscanf(buffer, "%% \tnumFirstAssignments %u",
- &global_Stats.archStats[i].numFirstAssignments);
- if (numScanned != 1) {
- BAD_INPUT;
- }
-
- @
-
-
- 1.10
- log
- @added missing statistic to checkpoint file
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.9 90/05/02 14:35:35 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d136 2
- d478 1
- d892 5
- a896 1
- if (reqMigdPtr->lastHostAssigned == infoPtr->hostID) {
- d903 10
- a912 1
- reqMigdPtr->lastHostAssigned = infoPtr->hostID;
- d1154 2
- d1559 5
- d1745 3
- d2006 4
- a2009 2
- fprintf(stderr, "Global_HostUp - %s boot %d version %d maxProcs %d\n",
- migdPtr->name, infoPtr->bootTime, infoPtr->migVersion,
- d2039 1
- a2039 1
- time.tv_sec - MIG_GLOBAL_UPDATE_INTERVAL) {
- a2073 1
- oldCltPtr->type = MIGD_CLOSED;
- d2100 1
- a2100 1
- infoPtr->state = MIG_HOST_REFUSES;
- d2104 1
- a2104 1
- if (infoPtr->state == MIG_HOST_IDLE) {
- d2193 5
- d2337 10
- a2346 1
- InsertIdle(migdPtr);
- d2645 2
- d2649 2
- d2883 7
- d2897 7
- d3265 1
- a3265 1
- if (global_Debug > 1) {
- @
-
-
- 1.9
- log
- @fixed problem with thinking process never denied a host if it eventually got
- as many as it could use, even if earlier it was denied.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.8 90/05/02 12:30:46 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d2624 3
- d2884 8
- @
-
-
- 1.8
- log
- @keep track of how many clients got as many hosts as they requested.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.7 90/04/27 00:59:05 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d937 1
- d1202 1
- a1202 1
- if (cltPtr->maxRequests == cltPtr->maxObtained) {
- @
-
-
- 1.7
- log
- @changes for statistics gathering.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.6 90/04/24 18:00:32 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d1004 2
- a1005 2
- for (i = 0; i < numArgs; i++) {
- status = Global_Done(cltPtr, *hostPtr);
- d1035 1
- a1035 1
- Global_Done(cltPtr, host)
- d1038 2
- d1158 1
- a1158 1
- if (host == MIG_ALL_HOSTS) {
- d1183 5
- a1187 1
- if (migd_DoStats) {
- d1201 3
- d2601 2
- d2827 7
- d2887 1
- a2887 1
- &global_Stats.archStats[i].counters.hostIdleObtained[MIG_COUNTER_HIGH],
- @
-
-
- 1.6
- log
- @intermediate checkpoint
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.5 90/04/03 11:08:25 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d224 1
- a224 1
- fprintf(stderr, "Global_Init - process %x version %d on host %s:\n",
- d359 1
- d724 1
- d737 1
- a771 2
- cltPtr->numRequested += numHosts;
-
- d775 17
- d880 19
- d945 7
- a951 1
- cltPtr->numAssigned += total;
- d1056 1
- d1122 1
- a1122 1
-
- d1143 9
- d1181 26
- a1206 4
- requests = max(cltPtr->maxRequests, MIG_MAX_HOSTS_DIST);
- obtained = max(cltPtr->maxObtained, MIG_MAX_HOSTS_DIST);
- global_Stats.archStats.requestDist[requests]++;
- global_Stats.archStats.obtainedDist[obtained]++;
- d1222 1
- a1222 1
- return(0);
- d1447 1
- d1457 13
- d1498 25
- d1844 4
- a1847 1
- if (global_Debug > 3) {
- d1849 1
- a1849 1
- fprintf(stderr, "Host is now idle.\n");
- a1857 1
- break;
- d2044 1
- a2044 1
- * of clock skew.
- d2046 4
- a2049 1
- migdPtr->info.loadVec.timestamp = time.tv_sec;
- a2054 1
- * InsertIdle changes the counters automatically.
- d2064 4
- a2067 3
- hostCounts[migdPtr->archType][MIG_HOST_DOWN]--;
- hostCounts[migdPtr->archType][infoPtr->state]++;
- } else if (infoPtr->state == MIG_HOST_IDLE) {
- a2068 3
- } else {
- hostCounts[migdPtr->archType][MIG_HOST_DOWN]--;
- hostCounts[migdPtr->archType][infoPtr->state]++;
- d2282 4
- a2285 1
- fprintf(stderr, "\t>>%s is no longer idle<<\n", migdPtr->name);
- a2286 1
- RecordEvictions(migdPtr);
- a2399 1
- PRINT_PID;
- d2447 1
- a2447 1
- int i, j;
- a2499 3
- fprintf(checkPoint, "%% Version %d HasStats %d last run on %s.\n",
- migd_Version, migd_DoStats, migd_HostName);
-
- d2579 8
- a2586 5
- fprintf(file, "%% firstRun %d\n", global_Stats.firstRun);
- fprintf(file, "%% restarts %d\n", global_Stats.restarts);
- fprintf(file, "%% intervals %d\n", global_Stats.intervals);
- fprintf(file, "%% maxArchs %d\n", global_Stats.maxArchs);
- fprintf(file, "%% getLoadRequests %d\n", global_Stats.getLoadRequests);
- d2588 1
- a2588 1
- fprintf(file, "%% arch %d %s\n",
- d2590 1
- a2590 1
- fprintf(file, "%% \tnumClients %d\n",
- d2592 1
- a2592 1
- fprintf(file, "%% \tnumRepeatAssignments %d\n",
- d2594 2
- d2597 1
- a2597 1
- fprintf(file, "%% \trequested %d %d\n",
- d2600 1
- a2600 1
- fprintf(file, "%% \tobtained %d %d\n",
- d2603 1
- a2603 1
- fprintf(file, "%% \tevicted %d %d\n",
- d2606 1
- a2606 1
- fprintf(file, "%% \treclaimed %d %d\n",
- d2609 1
- a2609 1
- fprintf(file, "%% \ttimeUsed %d %d\n",
- d2612 15
- a2626 12
- fprintf(file, "%% \thostIdleObtained %d %d\n",
- global_Stats.archStats[i].counters.hostIdleObtained,
- global_Stats.archStats[i].squared.hostIdleObtained);
- fprintf(file, "%% \thostIdleEvicted %d %d\n",
- global_Stats.archStats[i].counters.hostIdleEvicted,
- global_Stats.archStats[i].squared.hostIdleEvicted);
- fprintf(file, "%% \tnonIdleTransitions %d %d\n",
- global_Stats.archStats[i].counters.nonIdleTransitions,
- global_Stats.archStats[i].squared.nonIdleTransitions);
- fprintf(file, "%% \tidleTimeWhenActive %d %d\n",
- global_Stats.archStats[i].counters.idleTimeWhenActive,
- global_Stats.archStats[i].squared.idleTimeWhenActive);
- d2629 2
- a2630 2
- for (j = 0; j < MIG_MAX_HOSTS_DIST; j++) {
- fprintf(file, "%d ",
- d2636 2
- a2637 2
- for (j = 0; j < MIG_MAX_HOSTS_DIST; j++) {
- fprintf(file, "%d ",
- d2648 1
- a2648 1
- fprintf(file, "%d %d ",
- d2684 2
- d2733 3
- a2735 3
- numScanned = sscanf(buffer, "%% Version %d HasStats %d\n",
- &lastVersion, &didStats);
- if (numScanned != 2) {
- d2738 2
- a2739 1
- if (lastVersion != migd_Version) {
- d2743 3
- a2745 2
- "ReadStats: mismatch in migd versions: ours is %d but last writer\n\tof checkpoint was %d.\n",
- migd_Version, lastVersion);
- d2760 1
- a2760 1
- numScanned = sscanf(buffer, "%% firstRun %d", &global_Stats.firstRun);
- d2766 1
- a2766 1
- numScanned = sscanf(buffer, "%% restarts %d", &global_Stats.restarts);
- d2773 1
- a2773 1
- numScanned = sscanf(buffer, "%% intervals %d", &global_Stats.intervals);
- d2779 1
- a2779 6
- numScanned = sscanf(buffer, "%% maxArchs %d", &maxArchs);
- if (numScanned != 1) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% getLoadRequests %d", &getLoadRequests);
- d2792 6
- d2800 1
- a2800 1
- numScanned = sscanf(buffer, "%% arch %d %s", &archNum, archName);
- d2809 1
- a2809 1
- numScanned = sscanf(buffer, "%% \tnumClients %d",
- d2816 1
- a2816 1
- numScanned = sscanf(buffer, "%% \tnumRepeatAssignments %d",
- d2823 8
- a2830 1
- numScanned = sscanf(buffer, "%% \trequested %d %d",
- d2837 1
- a2837 1
- numScanned = sscanf(buffer, "%% \tobtained %d %d",
- d2844 1
- a2844 1
- numScanned = sscanf(buffer, "%% \tevicted %d %d",
- d2851 1
- a2851 9
- numScanned = sscanf(buffer, "%% \treclaimed %d %d",
- &global_Stats.archStats[i].counters.reclaimed,
- &global_Stats.archStats[i].squared.reclaimed);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \treclaimed %d %d",
- d2859 1
- a2859 1
- numScanned = sscanf(buffer, "%% \ttimeUsed %d %d",
- d2867 26
- a2892 28
- numScanned = sscanf(buffer, "%% \thostIdleObtained %d %d",
- &global_Stats.archStats[i].counters.hostIdleObtained,
- &global_Stats.archStats[i].squared.hostIdleObtained);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \thostIdleEvicted %d %d",
- &global_Stats.archStats[i].counters.hostIdleEvicted,
- &global_Stats.archStats[i].squared.hostIdleEvicted);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \tnonIdleTransitions %d %d",
- &global_Stats.archStats[i].counters.nonIdleTransitions,
- &global_Stats.archStats[i].squared.nonIdleTransitions);
-
- if (numScanned != 2) {
- BAD_INPUT;
- }
- READLINE;
- numScanned = sscanf(buffer, "%% \tidleTimeWhenActive %d %d",
- &global_Stats.archStats[i].counters.idleTimeWhenActive,
- &global_Stats.archStats[i].squared.idleTimeWhenActive);
- if (numScanned != 2) {
- d2910 2
- a2911 2
- for (j = 0; j < MIG_MAX_HOSTS_DIST; j++) {
- numScanned = fscanf(file, "%d ",
- d2945 2
- a2946 2
- for (j = 0; j < MIG_MAX_HOSTS_DIST; j++) {
- numScanned = fscanf(file, "%d ",
- d2981 1
- a2981 1
- numScanned = fscanf(file, "%d %d ",
- d3181 50
- a3230 4
- /*
- * XXX need to add this here.
- */
- return(EINVAL);
- d3232 1
- a3232 1
-
- @
-
-
- 1.5
- log
- @initialize host state properly if not allowing migration at start. print
- time of each ckpt for debugging.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.4 90/03/14 12:49:38 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d85 28
- d114 2
- a115 1
- static int maxArchTypes = 10; /* number of elements in arrays per-type */
- d130 9
- d141 2
- a142 1
- static int hostsUp = 0;
- d144 3
- d155 3
- d176 5
- d224 2
- a225 2
- fprintf(stderr, "Global_Init - process %x on host %s:\n",
- migd_Pid, migd_HostName);
- d310 8
- d319 2
- a320 1
- * list downtimes for hosts that aren't currently up.
- d324 1
- a324 1
- period.seconds = MIG_TIMEOUT;
- d337 39
- d470 1
- d616 1
- d722 1
- a722 1
- Migd_RequestInfo *reqPtr; /* Pointer to info for a request. */
- d769 2
- d826 1
- d835 1
- d847 1
- a847 1
- reqPtr = mnew(Migd_RequestInfo);
- d907 2
- a908 1
- cltPtr->numHostsUsed += total;
- a913 1
-
- d1003 1
- a1003 1
- int numReturned; /* Number of hosts returned. */
- d1008 1
- a1008 1
- Migd_RequestInfo *reqPtr; /* Pointer to info for a request. */
- d1010 3
- d1042 4
- a1045 1
- return((host != MIG_ALL_HOSTS) ? EINVAL : 0);
- a1050 1
- numReturned = 0;
- d1059 1
- a1059 1
- reqPtr = (Migd_RequestInfo *) cltListPtr;
- d1102 1
- d1104 4
- d1127 5
- d1142 1
- a1142 2
- * policy issues. Would also like to send message to anyone waiting
- * for hosts to be freed up.
- d1144 3
- d1183 1
- d1189 1
- d1204 1
- a1204 1
- migdPtr->name, migdPtr->info.loadVec.noInput,
- d1228 3
- a1230 4
- migdPtr->info.state = MIG_HOST_IDLE;
-
- return;
- }
- d1239 1
- a1239 1
- migdPtr->info.state = MIG_HOST_PART_USED;
- d1249 2
- a1250 2
- migdPtr->info.state = MIG_HOST_FULL;
- return;
- d1260 1
- a1260 1
- return;
- d1266 10
- d1368 1
- a1368 1
- Migd_RequestInfo *reqPtr;
- d1375 1
- a1375 1
- if (global_Debug > 1) {
- d1385 1
- a1385 1
- if (global_Debug > 2) {
- d1387 2
- a1388 1
- fprintf(stderr, "RecordEvictions: removing request from process %x.\n",
- d1744 1
- d1746 2
- a1747 1
-
- d1935 2
- a1936 1
- * Add the host to appropriate queue.
- d1946 3
- a1948 2
- }
- if (infoPtr->state == MIG_HOST_IDLE) {
- d1950 3
- d2044 1
- d2046 1
- d2122 1
- d2125 1
- d2169 1
- d2171 1
- d2205 2
- a2206 1
- * The state of each host in the checkpoint is initialized.
- d2220 1
- d2234 10
- d2288 4
- a2291 1
- migdPtr->info.state = MIG_HOST_DOWN;
- d2293 3
- a2295 3
- if (global_Debug > 2) {
- PRINT_PID;
- fprintf(stderr, "\nRestoreCheckPoint - returning.\n");
- d2330 1
- a2330 1
- int i;
- d2338 2
- a2339 1
- fprintf(stderr, "SaveCheckPoint - %s", ctime(&t));
- d2359 2
- a2360 2
- SYSLOG3(LOG_ERR,
- "\tdescriptor inode <%d,%d> version %d (presumably another migd running elsewhere).\n",
- d2383 7
- a2389 1
- fprintf(checkPoint, "%% Daemon last run on %s.\n", migd_HostName);
- d2444 446
- d2992 1
- a2992 1
- Migd_RequestInfo *reqPtr;
- @
-
-
- 1.4
- log
- @stat the lock file once at the beginning and compare from there.
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.3 90/03/12 13:44:57 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d1980 2
- a1981 1
- migdPtr->info.state = MIG_HOST_ACTIVE;
- d2170 1
- a2170 1
- struct timeval time;
- d2175 1
- d2177 1
- a2177 1
- fprintf(stderr, "SaveCheckPoint -\n");
- d2215 1
- a2215 1
- status = gettimeofday(&time, (struct timezone *) NULL);
- d2238 1
- a2238 1
- migdPtr->info.loadVec.timestamp < time.tv_sec - MIG_TIMEOUT) {
- d2243 1
- a2243 1
- migdPtr->name, time.tv_sec,
- @
-
-
- 1.3
- log
- @print pid's before messages in global log file; print dates here and
- there; open files in append mode; changed file names to be in admin
- subdir. [this is a recording. beep!]
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.2 90/02/28 10:45:36 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d116 1
- a117 1
-
- d214 6
- d1735 15
- a1749 2
- */
- if (migdPtr->info.loadVec.timestamp <
- a2171 1
- struct stat descAtts;
- a2181 15
- if (migd_LogToFiles) {
- PRINT_PID;
- fprintf(stderr, "Exiting: unable to stat %s: %s.\n",
- migd_GlobalPdevName, strerror(errno));
- }
- exit(1);
- }
- if (MigPdev_Stat(&descAtts) < 0) {
- SYSLOG1(LOG_ERR, "Exiting: unable to stat pdev descriptor: %s.\n",
- strerror(errno));
- if (migd_LogToFiles) {
- PRINT_PID;
- fprintf(stderr, "Exiting: unable to stat pdev descriptor: %s.\n",
- strerror(errno));
- }
- a2187 15
- if (migd_LogToFiles) {
- PRINT_PID;
- fprintf(stderr, "Exiting: unable to stat %s: %s.\n",
- MIGD_LOCK_FILE, strerror(errno));
- }
- exit(1);
- }
- if (fstat(lockDesc, &descAtts) < 0) {
- SYSLOG1(LOG_ERR, "Exiting: unable to stat lock descriptor: %s.\n",
- strerror(errno));
- if (migd_LogToFiles) {
- PRINT_PID;
- fprintf(stderr, "Exiting: unable to stat lock descriptor: %s.\n",
- strerror(errno));
- }
- d2192 2
- a2193 2
- SYSLOG3(LOG_ERR,
- "Exiting: mismatch statting files: name inode <%d,%d>, version %d\n",
- d2196 1
- a2196 1
- "\tdescriptor inode <%d,%d> version %d.\n",
- a2197 8
- if (migd_LogToFiles) {
- PRINT_PID;
- fprintf(stderr,
- "Exiting: mismatch statting files: name inode <%d,%d>, version %d,\n\tdescriptor inode <%d,%d>, version %d.\n",
- nameAtts.st_ino, nameAtts.st_devServerID,
- nameAtts.st_version, descAtts.st_ino,
- descAtts.st_devServerID, descAtts.st_version);
- }
- a2265 4
- if (migd_LogToFiles) {
- PRINT_PID;
- fprintf(stderr, "Error syncing checkpoint file to disk.\n");
- }
- @
-
-
- 1.2
- log
- @print msgs to both syslog & error log when appropriate. various bug
- fixes to handle host crashes & duplicate daemons, mostly. use the global
- daemon's timestamp to avoid clock skew problems. check to make sure the
- master pdev hasn't changed inodes on us (meaning there's another daemon
- around someplace).
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/global.c,v 1.1 90/02/15 19:17:39 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d106 1
- a106 1
- #define MIGD_CHECKPOINT_FILE "/sprite/admin/migd.check"
- d109 4
- d115 1
- d158 1
- d160 2
- d167 3
- d173 4
- a176 2
- fprintf(stderr, "Global_Init - process %x on host %s\n",
- getpid(), migd_HostName);
- d193 22
- d405 1
- d413 1
- d416 2
- d498 1
- d528 1
- d546 1
- d556 1
- d633 5
- a637 2
- SYSLOG0(LOG_WARNING,
- "Global_GetIdle: no daemon for requester's host.\n");
- d643 1
- d655 1
- d686 1
- d693 1
- d701 1
- d756 2
- a757 1
- if (global_Debug > 1) {
- d768 1
- d781 2
- a782 1
- if (global_Debug > 1) {
- d902 1
- a902 1
- if (global_Debug > 1) {
- d904 1
- d909 1
- d923 2
- a924 1
- if (global_Debug > 1) {
- d973 4
- a976 2
- }
- InsertIdle(migdPtr);
- d978 1
- d1010 1
- a1057 8
- if (!migdPtr->info.loadVec.allowMigration) {
- if (global_Debug > 0) {
- fprintf(stderr, "InsertIdle: %s not really available, so not doing anything.\n",
- migdPtr->name);
- }
- return;
- }
-
- d1073 1
- d1086 1
- d1093 1
- d1117 1
- d1125 1
- d1170 2
- a1171 1
- if (global_Debug > 1) {
- d1189 1
- d1238 1
- d1247 2
- a1248 1
- if (global_Debug > 1) {
- d1321 2
- a1322 1
- if (global_Debug) {
- d1336 1
- d1438 1
- d1444 1
- d1453 1
- d1462 1
- d1491 1
- d1544 1
- d1571 1
- d1584 1
- d1592 1
- d1599 1
- d1650 1
- d1654 6
- d1712 1
- d1720 21
- d1743 1
- d1751 1
- d1761 1
- a1775 5
- status = gettimeofday(&time, (struct timezone *) NULL);
- if (status == -1) {
- SYSLOG1(LOG_ERR, "Error in gettimeofday: %s", strerror(errno));
- exit(1);
- }
- d1783 9
- d1828 1
- d1863 1
- d1869 1
- d1945 1
- d1957 1
- d1966 1
- d2000 2
- a2001 1
- if (global_Debug > 1) {
- d2007 2
- a2008 1
- if (global_Debug > 1) {
- d2017 1
- d2056 1
- d2061 1
- d2071 3
- a2073 2
- if (global_Debug > 3) {
- fprintf(stderr, "RestoreCheckPoint - skipping line: %s",
- d2083 1
- d2090 1
- d2098 1
- d2104 1
- d2113 1
- d2155 2
- a2156 1
- if (global_Debug > 2) {
- d2160 1
- d2165 1
- d2175 1
- d2181 21
- d2203 7
- a2209 7
- nameAtts.st_devServerID != descAtts.st_devServerID) {
- SYSLOG2(LOG_ERR,
- "Exiting: mismatch statting pdevs: name inode <%d,%d>,\n",
- nameAtts.st_ino, nameAtts.st_devServerID);
- SYSLOG2(LOG_ERR,
- "\tdescriptor inode <%d,%d>.\n",
- descAtts.st_ino, descAtts.st_devServerID);
- d2211 1
- d2213 1
- a2213 1
- "Exiting: mismatch statting pdevs: name inode <%d,%d>,\n\tdescriptor inode <%d,%d>.\n",
- d2215 2
- a2216 1
- descAtts.st_ino, descAtts.st_devServerID);
- d2222 1
- d2238 1
- a2238 1
-
- d2258 1
- d2266 1
- d2270 1
- d2281 1
- a2281 1
- }
- d2287 1
- d2357 1
- d2363 1
- d2369 1
- d2403 1
- d2412 1
- d2461 1
- d2503 1
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d47 1
- a47 1
- static char rcsid[] = "$Header: /user2/douglis/pdev_mig/migd/RCS/global.c,v 2.4 90/02/14 11:45:17 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d64 1
- d67 1
- d189 1
- a189 1
- (maxArchTypes + 1));
- d265 1
- a265 1
- syslog(LOG_ERR, "invalid host ID from Host_Next: %d.\n",
- d275 1
- a275 1
- syslog(LOG_WARNING,
- d307 1
- a307 1
- syslog(LOG_WARNING,
- d376 3
- d465 1
- a465 1
- syslog(LOG_WARNING,
- d477 6
- a482 3
- syslog(LOG_WARNING,
- "Global_GetLoadInfo: bad firstHost argument (%d) or output buffer size (%d) for %d records, from process %x\n",
- firstHost,*outBufSizePtr, numRecs, cltPtr->processID);
- d577 1
- a577 1
- syslog(LOG_WARNING,
- d585 11
- d598 2
- a599 3
- "Global_GetIdle: request for %d hosts from process %x (virtually on %d, physically on %d)\n",
- numHosts, cltPtr->processID,
- requestPtr->virtHost, cltPtr->host);
- a614 10
- reqMigdPtr = migInfoArray[cltPtr->host];
- if (reqMigdPtr == (Migd_Info *) NULL ||
- reqMigdPtr->info.state == MIG_HOST_DOWN) {
- if (global_Debug > 0) {
- syslog(LOG_WARNING,
- "Global_GetIdle: no daemon for requester's host.\n");
- }
- return(ENOTCONN);
- }
-
- d789 1
- a789 1
- syslog(LOG_WARNING,
- d1265 1
- a1265 1
- syslog(LOG_WARNING,
- d1269 1
- a1269 1
- return(GEN_INVALID_ARG);
- d1277 1
- a1277 1
- return(GEN_FAILURE);
- d1331 1
- a1331 1
- syslog(LOG_WARNING,
- d1378 3
- a1380 1
- syslog(LOG_ERR, "RemoveHost: bad value of hostID: %d\n", hostID);
- d1386 4
- a1389 2
- syslog(LOG_ERR, "RemoveHost: %s is up; not removing.\n",
- migdPtr->name);
- d1427 1
- a1427 1
- syslog(LOG_ERR, "Global_IsHostUp: bad value of hostID: %d\n", hostID);
- d1484 1
- a1484 1
- syslog(LOG_WARNING,
- d1496 1
- a1496 1
- syslog(LOG_ERR, "Global_ChangeState: never heard from this host? Exiting.\n");
- d1572 2
- d1581 1
- a1581 1
- syslog(LOG_WARNING,
- d1585 1
- a1585 1
- return(GEN_INVALID_ARG);
- d1610 1
- a1610 1
- syslog(LOG_ERR,
- d1612 1
- a1612 1
- return(GEN_INVALID_ARG);
- d1622 1
- a1622 1
- syslog(LOG_ERR, "No entry in host database for host %d.\n",
- d1624 1
- a1624 1
- return(GEN_INVALID_ARG);
- d1637 1
- d1639 15
- a1653 5
- syslog(LOG_WARNING,
- "Already talking to a daemon on %s. Rejecting open.\n",
- migdPtr->name);
- cltPtr->type = MIGD_NEW;
- return(DEV_BUSY);
- d1655 2
- a1656 2
- if (global_Debug > 0) {
- syslog(LOG_WARNING,
- a1659 1
- oldCltPtr = migdPtr->cltPtr;
- d1662 12
- d1675 2
- a1676 1
- migdPtr->info = *infoPtr;
- d1821 2
- d1828 1
- a1828 1
- syslog(LOG_ERR, "Global_UpdateLoad: never heard from this host? Exiting.\n");
- d1866 14
- d1928 1
- d2000 4
- a2003 1
- * in a while.
- d2025 2
- d2031 41
- d2074 1
- a2074 1
- syslog(LOG_WARNING, "SaveCheckPoint - error writing checkpoint: %s.\n",
- d2080 2
- a2081 2
- syslog(LOG_ERR, "Error in gettimeofday: %s", strerror(errno));
- return;
- d2093 1
- a2093 1
- syslog(LOG_WARNING,
- d2125 7
- d2166 1
- a2166 1
- syslog(LOG_WARNING,
- @
-